required to apply R2R and Targets ... required to Apply Max Allowed TP ... required to Apply Guards ... required to Apply Tragets ...
3129 lines
73 KiB
Plaintext
3129 lines
73 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 X121 SMC Signal Class
|
|
// -------------------------------------------------
|
|
// Name: XWZ
|
|
// Description: provide all Signalling functions ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://www.saherelm.ir"
|
|
#property version "1.00"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
// #include "../../Libraries/x-trade.lib"
|
|
#include "../Classes/x-121.smc.market.cycle.helper.class.mq5"
|
|
#include "../Libraries/x-121.smc.guard.lib.mq5"
|
|
#include "../Libraries/x-121.smc.lib.mq5"
|
|
|
|
//
|
|
enum ENUM_X121SMC_XWZ_PRIORITY
|
|
{
|
|
X121SMC_XWZ_PRIORITY_NONE,
|
|
X121SMC_XWZ_PRIORITY_WEAK,
|
|
X121SMC_XWZ_PRIORITY_LOW,
|
|
X121SMC_XWZ_PRIORITY_REGULAR,
|
|
X121SMC_XWZ_PRIORITY_HIGH,
|
|
X121SMC_XWZ_PRIORITY_STRONG_HIGH,
|
|
};
|
|
|
|
//
|
|
struct X121SMCXWZZone
|
|
{
|
|
//
|
|
// Props ...
|
|
XCFVG *fvg;
|
|
XCOrderBlock *ob;
|
|
XCSupplyZone *supply;
|
|
XCDemandZone *demand;
|
|
XCSupportZone *support;
|
|
XCResistanceZone *resistance;
|
|
XConsolidationZone bullishConsolidationZone;
|
|
XConsolidationZone bearishConsolidationZone;
|
|
|
|
//
|
|
XOHCL swingBar;
|
|
XOHCL breakerBar;
|
|
XOHCL momentumBar;
|
|
XOHCL rejectionBar;
|
|
XBoxZone appliedBox;
|
|
|
|
//
|
|
// Constructor ...
|
|
X121SMCXWZZone()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
void Clean()
|
|
{
|
|
//
|
|
ZeroMemory(ob);
|
|
ZeroMemory(fvg);
|
|
ZeroMemory(supply);
|
|
ZeroMemory(demand);
|
|
ZeroMemory(support);
|
|
ZeroMemory(resistance);
|
|
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
bullishConsolidationZone.Clean();
|
|
bearishConsolidationZone.Clean();
|
|
}
|
|
|
|
//
|
|
bool IsValid()
|
|
{
|
|
//
|
|
return HasOB() &&
|
|
HasFVG() &&
|
|
HasDirection();
|
|
}
|
|
|
|
//
|
|
bool AsBox(XBoxZone &box)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
result = IsValid() &&
|
|
HasDirection();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone obBox;
|
|
bool hasOBBox = ToBox(
|
|
obBox,
|
|
ob //
|
|
);
|
|
result = hasOBBox;
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
obBox.Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
box = obBox;
|
|
|
|
//
|
|
obBox.Clean();
|
|
|
|
//
|
|
bool hasOB = HasOB();
|
|
bool hasFVG = HasFVG();
|
|
bool hasSupply = HasSupply();
|
|
bool hasDemand = HasDemand();
|
|
bool hasSupport = HasSupport();
|
|
bool hasResistance = HasResistance();
|
|
|
|
//
|
|
// OB Compared since box used obBox ...
|
|
|
|
//
|
|
if (hasFVG)
|
|
{
|
|
//
|
|
if (fvg.Upper() > box.upper)
|
|
{
|
|
box.upper = fvg.Upper();
|
|
}
|
|
|
|
//
|
|
if (fvg.Lower() < box.lower)
|
|
{
|
|
box.lower = fvg.Lower();
|
|
}
|
|
}
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasOB()
|
|
{
|
|
return ob != NULL &&
|
|
ob.IsValid();
|
|
}
|
|
|
|
//
|
|
bool HasFVG()
|
|
{
|
|
return fvg != NULL &&
|
|
fvg.IsValid();
|
|
}
|
|
|
|
//
|
|
bool HasSupply()
|
|
{
|
|
return supply != NULL &&
|
|
supply.IsValid();
|
|
}
|
|
|
|
//
|
|
bool HasDemand()
|
|
{
|
|
return demand != NULL &&
|
|
demand.IsValid();
|
|
}
|
|
|
|
//
|
|
bool HasSupport()
|
|
{
|
|
return support != NULL &&
|
|
support.IsValid();
|
|
}
|
|
|
|
//
|
|
bool HasResistance()
|
|
{
|
|
return resistance != NULL &&
|
|
resistance.IsValid();
|
|
}
|
|
|
|
//
|
|
bool HasBullishConsolidationZone()
|
|
{
|
|
return bullishConsolidationZone.IsValid() &&
|
|
bullishConsolidationZone.IsBreaked() &&
|
|
IsBullish(bullishConsolidationZone.breakDir);
|
|
}
|
|
|
|
//
|
|
bool HasBearishConsolidationZone()
|
|
{
|
|
return bearishConsolidationZone.IsValid() &&
|
|
bearishConsolidationZone.IsBreaked() &&
|
|
IsBullish(bearishConsolidationZone.breakDir);
|
|
}
|
|
|
|
//
|
|
bool IsBullish()
|
|
{
|
|
//
|
|
return HasOB() &&
|
|
ob.IsBullish() &&
|
|
HasFVG() &&
|
|
fvg.IsBullish() &&
|
|
HasSupport() &&
|
|
HasDemand();
|
|
}
|
|
|
|
//
|
|
bool IsBearish()
|
|
{
|
|
//
|
|
return HasOB() &&
|
|
ob.IsBearish() &&
|
|
HasFVG() &&
|
|
fvg.IsBearish() &&
|
|
HasSupply() &&
|
|
HasResistance();
|
|
}
|
|
|
|
//
|
|
bool HasDirection()
|
|
{
|
|
return IsBullish() ||
|
|
IsBearish();
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION GetDirection()
|
|
{
|
|
//
|
|
ENUM_X_DIRECTION result = X_DIRECTION_NONE;
|
|
|
|
//
|
|
bool hasDirection = HasDirection();
|
|
if (!hasDirection)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish();
|
|
|
|
//
|
|
result =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasCondition(
|
|
XPOIState &state,
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
result = IsValid() &&
|
|
HasDirection() &&
|
|
state.IsValid() &&
|
|
state.HasChild();
|
|
if (!result)
|
|
{
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string symbol = ob.GetSymbol();
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = ob.GetPeriod();
|
|
}
|
|
datetime cTime = iTime(
|
|
symbol,
|
|
forPeriod,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
XBoxZone box;
|
|
result = AsBox(box);
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish();
|
|
ENUM_X_DIRECTION forDir = box.dir;
|
|
|
|
//
|
|
int supportsCount = 0;
|
|
bool hasSupports = false;
|
|
XCSupportZone *supports[];
|
|
|
|
//
|
|
int resistancesCount = 0;
|
|
bool hasResistances = false;
|
|
XCResistanceZone *resistances[];
|
|
|
|
//
|
|
XBoxZone supResBoxes[];
|
|
int supresBoxesCount = 0;
|
|
bool hasSupResBoxes = false;
|
|
|
|
//
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
has = state.HasSupportZones();
|
|
if (has)
|
|
{
|
|
//
|
|
count = state.CountSupportZones();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCSupportZone *iZone = state.supportZones[i];
|
|
|
|
//
|
|
iZone.To(cTime);
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
bool hasBox = ToBox(
|
|
iBox,
|
|
iZone //
|
|
);
|
|
if (!hasBox)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check From ...
|
|
bool isInside = IsBoxInside(
|
|
iBox,
|
|
box //
|
|
);
|
|
if (!isInside)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
iZone,
|
|
supports //
|
|
);
|
|
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
supResBoxes //
|
|
);
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
supportsCount = ArraySize(supports);
|
|
hasSupports = IsValidSize(supportsCount);
|
|
|
|
//
|
|
supresBoxesCount = ArraySize(supResBoxes);
|
|
hasSupResBoxes = IsValidSize(supresBoxesCount);
|
|
}
|
|
|
|
//
|
|
has = state.HasResistanceZones();
|
|
if (has)
|
|
{
|
|
//
|
|
count = state.CountResistanceZones();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCResistanceZone *iZone = state.resistanceZones[i];
|
|
|
|
//
|
|
iZone.To(cTime);
|
|
|
|
//
|
|
XBoxZone iBox;
|
|
bool hasBox = ToBox(
|
|
iBox,
|
|
iZone //
|
|
);
|
|
if (!hasBox)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check From ...
|
|
bool isInside = IsBoxInside(
|
|
iBox,
|
|
box //
|
|
);
|
|
if (!isInside)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
iZone,
|
|
resistances //
|
|
);
|
|
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
supResBoxes //
|
|
);
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
resistancesCount = ArraySize(resistances);
|
|
hasResistances = IsValidSize(resistancesCount);
|
|
|
|
//
|
|
supresBoxesCount = ArraySize(supResBoxes);
|
|
hasSupResBoxes = IsValidSize(supresBoxesCount);
|
|
}
|
|
|
|
//
|
|
result = hasSupResBoxes;
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
Clean(supports);
|
|
Clean(resistances);
|
|
Clean(supResBoxes);
|
|
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detect Bars ...
|
|
|
|
//
|
|
XOHCL zBar;
|
|
result = zBar.Init(
|
|
symbol,
|
|
forPeriod,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
zBar.Clean();
|
|
Clean(supports);
|
|
Clean(resistances);
|
|
Clean(supResBoxes);
|
|
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL cBar;
|
|
result = zBar.GetPreviousBar(cBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
Clean(supports);
|
|
Clean(resistances);
|
|
Clean(supResBoxes);
|
|
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL pBar;
|
|
result = cBar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
Clean(supports);
|
|
Clean(resistances);
|
|
Clean(supResBoxes);
|
|
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL ppBar;
|
|
result = pBar.GetPreviousBar(ppBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
ppBar.Clean();
|
|
Clean(supports);
|
|
Clean(resistances);
|
|
Clean(supResBoxes);
|
|
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Conditions ...
|
|
|
|
//
|
|
// Detect Start Senario ...
|
|
|
|
//
|
|
double fiboPressureLevel = GetFiboLevelValue(X_FIBO_LEVEL_382);
|
|
|
|
//
|
|
double fiboUpDown = GetFibonacciLevel(
|
|
pBar.high,
|
|
pBar.low,
|
|
X_FIBO_LEVEL_382,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
double fiboDownUp = GetFibonacciLevel(
|
|
pBar.high,
|
|
pBar.low,
|
|
X_FIBO_LEVEL_382,
|
|
X_DIRECTION_BULLISH //
|
|
);
|
|
|
|
//
|
|
bool hasFiboToUpPressure =
|
|
fiboDownUp > 0 &&
|
|
fiboDownUp <= pBar.GetDown();
|
|
bool hasFiboToDownPressure =
|
|
fiboUpDown > 0 &&
|
|
fiboUpDown >= pBar.GetUp();
|
|
|
|
//
|
|
int selectedBoxIDX = -1;
|
|
for (int j = 0; j < supresBoxesCount; j++)
|
|
{
|
|
//
|
|
double appliedPrice =
|
|
isBullish
|
|
? supResBoxes[j].lower
|
|
: supResBoxes[j].upper;
|
|
//
|
|
// Check Swing Low ...
|
|
bool isSwingLow =
|
|
//
|
|
pBar.low < ppBar.low &&
|
|
pBar.low < cBar.low &&
|
|
zBar.open > pBar.low &&
|
|
//
|
|
appliedPrice > pBar.low &&
|
|
appliedPrice < pBar.GetDown()
|
|
//
|
|
;
|
|
bool isPressuredSwingLow =
|
|
isSwingLow &&
|
|
hasFiboToUpPressure;
|
|
bool isPressuredStrongSwingLow =
|
|
pBar.IsBullish() &&
|
|
isPressuredSwingLow;
|
|
|
|
//
|
|
bool isSwingHigh =
|
|
//
|
|
pBar.high > ppBar.high &&
|
|
pBar.high > cBar.high &&
|
|
zBar.open < pBar.high &&
|
|
//
|
|
appliedPrice < pBar.high &&
|
|
appliedPrice > pBar.GetUp()
|
|
//
|
|
;
|
|
bool isPressuredSwingHigh =
|
|
isSwingHigh &&
|
|
hasFiboToDownPressure;
|
|
bool isPressuredStrongSwingHigh =
|
|
pBar.IsBearish() &&
|
|
isPressuredSwingHigh;
|
|
|
|
//
|
|
bool hasValidSwing =
|
|
isBullish
|
|
? isSwingLow
|
|
: isSwingHigh;
|
|
bool hasValidPressuredSwing =
|
|
isBullish
|
|
? isPressuredSwingLow
|
|
: isPressuredSwingHigh;
|
|
bool hasValidPressuredStrongSwing =
|
|
isBullish
|
|
? isPressuredStrongSwingLow
|
|
: isPressuredStrongSwingHigh;
|
|
if (hasValidSwing)
|
|
{
|
|
swingBar = pBar;
|
|
}
|
|
if (hasValidPressuredSwing)
|
|
{
|
|
swingBar = pBar;
|
|
}
|
|
if (hasValidPressuredStrongSwing)
|
|
{
|
|
swingBar = pBar;
|
|
}
|
|
|
|
//
|
|
bool isCBarBreaked = IsBarBreak(
|
|
appliedPrice,
|
|
forDir,
|
|
cBar //
|
|
);
|
|
if (isCBarBreaked)
|
|
{
|
|
breakerBar = cBar;
|
|
}
|
|
bool isPBarBreaked = IsBarBreak(
|
|
appliedPrice,
|
|
forDir,
|
|
pBar //
|
|
);
|
|
if (!isCBarBreaked && isPBarBreaked)
|
|
{
|
|
breakerBar = pBar;
|
|
}
|
|
else
|
|
{
|
|
isPBarBreaked = false;
|
|
}
|
|
bool isPPBarBreaked = IsBarBreak(
|
|
appliedPrice,
|
|
forDir,
|
|
ppBar //
|
|
);
|
|
if (!isCBarBreaked &&
|
|
!isPBarBreaked &&
|
|
isPPBarBreaked)
|
|
{
|
|
breakerBar = ppBar;
|
|
}
|
|
else
|
|
{
|
|
isPPBarBreaked = false;
|
|
}
|
|
bool isBoxBreaked = isCBarBreaked ||
|
|
isPBarBreaked ||
|
|
isPPBarBreaked;
|
|
|
|
//
|
|
bool isCBarRejected = IsBarReject(
|
|
appliedPrice,
|
|
forDir,
|
|
cBar //
|
|
);
|
|
if (isCBarRejected)
|
|
{
|
|
rejectionBar = cBar;
|
|
}
|
|
bool isPBarRejected = IsBarReject(
|
|
appliedPrice,
|
|
forDir,
|
|
pBar //
|
|
);
|
|
if (!isCBarRejected && isPBarRejected)
|
|
{
|
|
rejectionBar = pBar;
|
|
}
|
|
else
|
|
{
|
|
isPBarRejected = false;
|
|
}
|
|
bool isPPBarRejected = IsBarReject(
|
|
appliedPrice,
|
|
forDir,
|
|
ppBar //
|
|
);
|
|
if (!isCBarRejected &&
|
|
!isPBarRejected &&
|
|
isPPBarRejected)
|
|
{
|
|
rejectionBar = ppBar;
|
|
}
|
|
else
|
|
{
|
|
isPPBarRejected = false;
|
|
}
|
|
bool isBoxRejected = isCBarRejected ||
|
|
isPBarRejected ||
|
|
isPPBarRejected;
|
|
|
|
//
|
|
bool hasRejectionBar = false;
|
|
if (isBullish)
|
|
{
|
|
//
|
|
count = state.CountBullishRejectionBars();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCRejectionBar *iZone = state.bullishRejectionBars[i];
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isFilled = iZone.FillBar(iBar);
|
|
if (!isFilled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
int iBarIndex = iBar.Index();
|
|
|
|
//
|
|
hasRejectionBar =
|
|
//
|
|
(iBarIndex == cBar.Index() ||
|
|
iBarIndex == pBar.Index())
|
|
//
|
|
;
|
|
if (hasRejectionBar)
|
|
{
|
|
//
|
|
if (!rejectionBar.IsValid())
|
|
{
|
|
rejectionBar = iBar;
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
count = state.CountBearishRejectionBars();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCRejectionBar *iZone = state.bearishRejectionBars[i];
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isFilled = iZone.FillBar(iBar);
|
|
if (!isFilled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
int iBarIndex = iBar.Index();
|
|
|
|
//
|
|
hasRejectionBar =
|
|
//
|
|
(iBarIndex == cBar.Index() ||
|
|
iBarIndex == pBar.Index())
|
|
//
|
|
;
|
|
if (hasRejectionBar)
|
|
{
|
|
//
|
|
if (!rejectionBar.IsValid())
|
|
{
|
|
rejectionBar = iBar;
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
bool hasMomentumBar = false;
|
|
if (isBullish)
|
|
{
|
|
//
|
|
count = state.CountBullishMomentumBars();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCMomentumBar *iZone = state.bullishMomentumBars[i];
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isFilled = iZone.FillBar(iBar);
|
|
if (!isFilled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
int iBarIndex = iBar.Index();
|
|
|
|
//
|
|
hasMomentumBar =
|
|
//
|
|
(iBarIndex == cBar.Index() ||
|
|
iBarIndex == pBar.Index())
|
|
//
|
|
;
|
|
if (hasMomentumBar)
|
|
{
|
|
//
|
|
if (!momentumBar.IsValid())
|
|
{
|
|
momentumBar = iBar;
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
count = state.CountBearishMomentumBars();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCMomentumBar *iZone = state.bearishMomentumBars[i];
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isFilled = iZone.FillBar(iBar);
|
|
if (!isFilled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
int iBarIndex = iBar.Index();
|
|
|
|
//
|
|
hasMomentumBar =
|
|
//
|
|
(iBarIndex == cBar.Index() ||
|
|
iBarIndex == pBar.Index())
|
|
//
|
|
;
|
|
if (hasMomentumBar)
|
|
{
|
|
//
|
|
if (!momentumBar.IsValid())
|
|
{
|
|
momentumBar = iBar;
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
bool hasSwing = false;
|
|
if (isBullish)
|
|
{
|
|
//
|
|
count = state.CountSwingLows();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCSwing *iSwing = state.swingLows[i];
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isFilled = iSwing.FillBar(iBar);
|
|
if (!isFilled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
int iBarIndex = iBar.Index();
|
|
|
|
//
|
|
hasSwing =
|
|
//
|
|
(iBarIndex == cBar.Index() ||
|
|
iBarIndex == pBar.Index())
|
|
//
|
|
;
|
|
if (hasSwing)
|
|
{
|
|
//
|
|
if (!swingBar.IsValid())
|
|
{
|
|
swingBar = iBar;
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
count = state.CountSwingHighs();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCSwing *iSwing = state.swingHighs[i];
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isFilled = iSwing.FillBar(iBar);
|
|
if (!isFilled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
int iBarIndex = iBar.Index();
|
|
|
|
//
|
|
hasSwing =
|
|
//
|
|
(iBarIndex == cBar.Index() ||
|
|
iBarIndex == pBar.Index())
|
|
//
|
|
;
|
|
if (hasSwing)
|
|
{
|
|
//
|
|
if (!swingBar.IsValid())
|
|
{
|
|
swingBar = iBar;
|
|
}
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
bool hasRequiredValidations =
|
|
//
|
|
(hasRejectionBar ||
|
|
hasMomentumBar)
|
|
//
|
|
||
|
|
//
|
|
(hasRejectionBar ||
|
|
hasSwing)
|
|
//
|
|
||
|
|
//
|
|
(hasMomentumBar ||
|
|
hasSwing)
|
|
//
|
|
;
|
|
|
|
//
|
|
result =
|
|
//
|
|
(isBoxBreaked &&
|
|
(hasRequiredValidations ||
|
|
hasValidPressuredSwing))
|
|
//
|
|
||
|
|
//
|
|
(isBoxRejected &&
|
|
(hasRequiredValidations ||
|
|
hasValidPressuredSwing))
|
|
//
|
|
;
|
|
if (result)
|
|
{
|
|
//
|
|
selectedBoxIDX = j;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result =
|
|
result &&
|
|
(isBullish
|
|
? zBar.open > box.upper
|
|
: zBar.open < box.lower) &&
|
|
IsValidIndex(selectedBoxIDX);
|
|
if (result)
|
|
{
|
|
appliedBox = supResBoxes[selectedBoxIDX];
|
|
}
|
|
|
|
//
|
|
box.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
ppBar.Clean();
|
|
Clean(supports);
|
|
Clean(resistances);
|
|
Clean(supResBoxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
struct X121SMCXWZWorkingZone
|
|
{
|
|
//
|
|
string symbol;
|
|
ENUM_TIMEFRAMES period;
|
|
|
|
//
|
|
double upper;
|
|
double lower;
|
|
|
|
//
|
|
double zoneUpper;
|
|
double zoneLower;
|
|
|
|
//
|
|
double quarter1;
|
|
double quarter2;
|
|
double quarter3;
|
|
|
|
//
|
|
datetime to;
|
|
datetime from;
|
|
|
|
//
|
|
X121SMCXWZWorkingZone()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
void Clean()
|
|
{
|
|
//
|
|
upper = 0;
|
|
lower = 0;
|
|
quarter1 = 0;
|
|
quarter2 = 0;
|
|
quarter3 = 0;
|
|
zoneLower = 0;
|
|
zoneUpper = 0;
|
|
|
|
//
|
|
from = NULL;
|
|
symbol = NULL;
|
|
period = NULL;
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
//
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
lower > 0 &&
|
|
upper > 0 &&
|
|
quarter1 > 0 &&
|
|
quarter2 > 0 &&
|
|
quarter3 > 0 &&
|
|
upper > lower &&
|
|
zoneLower > 0 &&
|
|
zoneUpper > 0 &&
|
|
IsValid(from) &&
|
|
IsValid(symbol) &&
|
|
IsValid(period) &&
|
|
zoneUpper > upper &&
|
|
zoneLower < lower;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool DetectOveralTrend(
|
|
XOHCL &touchedBar,
|
|
ENUM_X_DIRECTION &trendDir,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
trendDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int fromBarIndex = iBarShift(
|
|
symbol,
|
|
period,
|
|
from //
|
|
);
|
|
result = IsValidIndex(fromBarIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL nearestUpperTouchedBar;
|
|
XOHCL nearestLowerTouchedBar;
|
|
bool hasNearestUpperTouchedBar = false;
|
|
bool hasNearestLowerTouchedBar = false;
|
|
for (int i = barIndex; i < fromBarIndex; i++)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool isInited = iBar.Init(
|
|
symbol,
|
|
period,
|
|
i //
|
|
);
|
|
|
|
//
|
|
hasNearestUpperTouchedBar = nearestUpperTouchedBar.IsValid();
|
|
if (!hasNearestUpperTouchedBar)
|
|
{
|
|
//
|
|
bool isBarTouchedUpper = iBar.high > upper;
|
|
if (isBarTouchedUpper)
|
|
{
|
|
//
|
|
nearestUpperTouchedBar = iBar;
|
|
hasNearestUpperTouchedBar = true;
|
|
}
|
|
}
|
|
|
|
//
|
|
hasNearestLowerTouchedBar = nearestLowerTouchedBar.IsValid();
|
|
if (!hasNearestLowerTouchedBar)
|
|
{
|
|
//
|
|
bool isBarTouchedLower = iBar.low < lower;
|
|
if (isBarTouchedLower)
|
|
{
|
|
//
|
|
nearestLowerTouchedBar = iBar;
|
|
hasNearestLowerTouchedBar = true;
|
|
}
|
|
}
|
|
|
|
//
|
|
if (hasNearestUpperTouchedBar &&
|
|
hasNearestLowerTouchedBar)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = hasNearestUpperTouchedBar ||
|
|
hasNearestLowerTouchedBar;
|
|
if (result)
|
|
{
|
|
//
|
|
if (hasNearestUpperTouchedBar &&
|
|
!hasNearestLowerTouchedBar)
|
|
{
|
|
//
|
|
trendDir = X_DIRECTION_BEARISH;
|
|
touchedBar = nearestUpperTouchedBar;
|
|
}
|
|
else if (!hasNearestUpperTouchedBar &&
|
|
hasNearestLowerTouchedBar)
|
|
{
|
|
//
|
|
trendDir = X_DIRECTION_BULLISH;
|
|
touchedBar = nearestLowerTouchedBar;
|
|
}
|
|
else if (hasNearestUpperTouchedBar &&
|
|
hasNearestLowerTouchedBar)
|
|
{
|
|
//
|
|
trendDir =
|
|
nearestUpperTouchedBar.time < nearestLowerTouchedBar.time
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
if (IsBullish(trendDir))
|
|
{
|
|
touchedBar = nearestLowerTouchedBar;
|
|
}
|
|
else
|
|
{
|
|
touchedBar = nearestUpperTouchedBar;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool IsDestroyed(
|
|
ENUM_X_DIRECTION &destroyedDir,
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
destroyedDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL bar;
|
|
result = bar.Init(
|
|
symbol,
|
|
forPeriod,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isUpperBreaked =
|
|
bar.high > zoneUpper &&
|
|
bar.close > zoneUpper;
|
|
|
|
//
|
|
bool isLowerBreaked =
|
|
bar.low < zoneLower &&
|
|
bar.close < zoneLower;
|
|
|
|
//
|
|
result = isUpperBreaked ||
|
|
isLowerBreaked;
|
|
if (result)
|
|
{
|
|
//
|
|
destroyedDir =
|
|
isUpperBreaked
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
// Definitions ...
|
|
struct X121SMCStrategyXWZSignalConditions
|
|
{
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
string symbol;
|
|
ENUM_TIMEFRAMES period;
|
|
|
|
//
|
|
double sl;
|
|
double target;
|
|
double reward;
|
|
double amountPercent;
|
|
ENUM_X_DIRECTION dir;
|
|
ENUM_X_POSITION_TYPES type;
|
|
|
|
//
|
|
// Setup Props ...
|
|
|
|
//
|
|
datetime setupTime;
|
|
datetime triggerTime;
|
|
|
|
//
|
|
double pivot;
|
|
double point;
|
|
|
|
//
|
|
ENUM_X121SMC_XWZ_PRIORITY priority;
|
|
|
|
//
|
|
// Working Zone ...
|
|
XCFVG *fairValueGap;
|
|
XCOrderBlock *orderBlock;
|
|
XCSupplyZone *supplyZone;
|
|
XCDemandZone *demandZone;
|
|
X121SMCXWZWorkingZone workingZone;
|
|
|
|
//
|
|
X121SMCXWZZone startZone;
|
|
|
|
//
|
|
// Constructor ...
|
|
X121SMCStrategyXWZSignalConditions()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
/**
|
|
* Cleaning Up ...
|
|
*/
|
|
void Clean()
|
|
{
|
|
//
|
|
sl = 0;
|
|
target = 0;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
type = X_POSITION_TYPE_NONE;
|
|
|
|
//
|
|
symbol = NULL;
|
|
period = NULL;
|
|
setupTime = NULL;
|
|
triggerTime = NULL;
|
|
|
|
//
|
|
ExtensionClean();
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
/**
|
|
* Check Condition is Setting Up ...
|
|
*
|
|
* @param dir: ENUM_X_DIRECTION member, Setting Up Direction ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsSetuped()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = IsValid(setupTime) &&
|
|
HasDirection(dir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Calculate Setup Age ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetSetupAge()
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (!IsSetuped())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = (int)(TimeCurrent() - setupTime) / PeriodSeconds(period);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect How we Can Trigger Signal ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool CanTrigger()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
sl > 0 &&
|
|
IsValid(symbol) &&
|
|
IsValid(period) &&
|
|
IsValid(triggerTime) &&
|
|
type != X_POSITION_TYPE_ALL &&
|
|
type != X_POSITION_TYPE_NONE
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extensions ...
|
|
|
|
/**
|
|
* Clean Additional Properties ...
|
|
*/
|
|
void ExtensionClean()
|
|
{
|
|
//
|
|
pivot = 0;
|
|
point = 0;
|
|
|
|
//
|
|
target = 0;
|
|
reward = 0;
|
|
amountPercent = 0;
|
|
|
|
//
|
|
ZeroMemory(supplyZone);
|
|
|
|
//
|
|
ZeroMemory(demandZone);
|
|
|
|
//
|
|
ZeroMemory(orderBlock);
|
|
|
|
//
|
|
ZeroMemory(fairValueGap);
|
|
|
|
//
|
|
startZone.Clean();
|
|
|
|
//
|
|
workingZone.Clean();
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
//
|
|
bool HasWorkingZone()
|
|
{
|
|
return workingZone.IsValid();
|
|
}
|
|
|
|
//
|
|
bool HasOrderBlock()
|
|
{
|
|
return orderBlock != NULL &&
|
|
orderBlock.IsValid();
|
|
}
|
|
|
|
//
|
|
bool HasFairValueGap()
|
|
{
|
|
return fairValueGap != NULL &&
|
|
fairValueGap.IsValid();
|
|
}
|
|
|
|
//
|
|
bool HasSupplyZone()
|
|
{
|
|
return supplyZone != NULL &&
|
|
supplyZone.IsValid();
|
|
}
|
|
|
|
//
|
|
bool HasDemandZone()
|
|
{
|
|
return demandZone != NULL &&
|
|
demandZone.IsValid();
|
|
}
|
|
|
|
//
|
|
bool HasStartZone()
|
|
{
|
|
return startZone.IsValid();
|
|
}
|
|
|
|
//
|
|
void UpdateTo(datetime value = NULL)
|
|
{
|
|
//
|
|
value = NormalizeTime(value);
|
|
|
|
//
|
|
bool hasSupplyZone = HasSupplyZone();
|
|
if (hasSupplyZone)
|
|
{
|
|
supplyZone.To(value);
|
|
}
|
|
|
|
//
|
|
bool hasDemandZone = HasDemandZone();
|
|
if (hasDemandZone)
|
|
{
|
|
demandZone.To(value);
|
|
}
|
|
|
|
//
|
|
bool hasOrderBlock = HasOrderBlock();
|
|
if (hasOrderBlock)
|
|
{
|
|
orderBlock.To(value);
|
|
}
|
|
|
|
//
|
|
bool hasFairValueGap = HasFairValueGap();
|
|
if (hasFairValueGap)
|
|
{
|
|
fairValueGap.To(value);
|
|
}
|
|
|
|
//
|
|
// Working Zone ...
|
|
bool hasWorkingZone = HasWorkingZone();
|
|
if (hasWorkingZone)
|
|
{
|
|
workingZone.to = value;
|
|
}
|
|
|
|
//
|
|
// Start Zone ...
|
|
bool hasStartZone = HasStartZone();
|
|
if (hasStartZone)
|
|
{
|
|
//
|
|
bool hasOB = startZone.HasOB();
|
|
if (hasOB)
|
|
{
|
|
startZone.ob.To(value);
|
|
}
|
|
|
|
//
|
|
bool hasFVG = startZone.HasFVG();
|
|
if (hasFVG)
|
|
{
|
|
startZone.fvg.To(value);
|
|
}
|
|
|
|
//
|
|
bool hasSupply = startZone.HasSupply();
|
|
if (hasSupply)
|
|
{
|
|
startZone.supply.To(value);
|
|
}
|
|
|
|
//
|
|
bool hasDemand = startZone.HasDemand();
|
|
if (hasDemand)
|
|
{
|
|
startZone.demand.To(value);
|
|
}
|
|
|
|
//
|
|
bool hasSupport = startZone.HasSupport();
|
|
if (hasSupport)
|
|
{
|
|
startZone.support.To(value);
|
|
}
|
|
|
|
//
|
|
bool hasResistance = startZone.HasResistance();
|
|
if (hasResistance)
|
|
{
|
|
startZone.resistance.To(value);
|
|
}
|
|
|
|
//
|
|
bool hasBullishCZone = startZone.HasBullishConsolidationZone();
|
|
if (hasBullishCZone)
|
|
{
|
|
// startZone.bullishConsolidationZone.to = cTime;
|
|
}
|
|
|
|
//
|
|
bool hasBearishCZone = startZone.HasBearishConsolidationZone();
|
|
if (hasBearishCZone)
|
|
{
|
|
// startZone.bearishConsolidationZone.to = cTime;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
//
|
|
// Working Zone is an Area which
|
|
// we decide to trade inside it ...
|
|
bool ExtractWorkingZone(
|
|
XPOIState &htfState,
|
|
XPOIState &mtfState,
|
|
XPOIState &stfState,
|
|
int barIndex = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
int zIndex = barIndex;
|
|
|
|
//
|
|
result = !HasWorkingZone();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsValid(symbol) &&
|
|
IsValid(period);
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
datetime cTime = iTime(
|
|
symbol,
|
|
period,
|
|
zIndex //
|
|
);
|
|
|
|
//
|
|
result =
|
|
//
|
|
htfState.IsValid() &&
|
|
htfState.HasChild() &&
|
|
htfState.HasSupplyZones() &&
|
|
htfState.HasDemandZones() &&
|
|
//
|
|
mtfState.IsValid() &&
|
|
mtfState.HasChild() &&
|
|
mtfState.HasSupplyZones() &&
|
|
mtfState.HasDemandZones() &&
|
|
//
|
|
stfState.IsValid() &&
|
|
stfState.HasChild()
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Highest Supply Zone ...
|
|
int hSupplyIDX = GetHighest(htfState.supplyZones);
|
|
int lDemandIDX = GetLowest(htfState.demandZones);
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValidIndex(hSupplyIDX) &&
|
|
IsValidIndex(lDemandIDX)
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
supplyZone = htfState.supplyZones[hSupplyIDX];
|
|
demandZone = htfState.demandZones[lDemandIDX];
|
|
|
|
//
|
|
result =
|
|
//
|
|
supplyZone != NULL &&
|
|
demandZone != NULL &&
|
|
supplyZone.IsValid() &&
|
|
demandZone.IsValid()
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Validation of Supply and Demand Zones ...
|
|
lDemandIDX = GetLowest(mtfState.demandZones);
|
|
hSupplyIDX = GetHighest(mtfState.supplyZones);
|
|
result = IsValidIndex(lDemandIDX) &&
|
|
IsValidIndex(hSupplyIDX);
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate Supply and Demand ...
|
|
bool isMTFHSupplyInside =
|
|
IsInside(
|
|
mtfState.supplyZones[hSupplyIDX],
|
|
supplyZone);
|
|
bool isMTFLDemandInside =
|
|
IsInside(
|
|
mtfState.demandZones[lDemandIDX],
|
|
demandZone //
|
|
);
|
|
if (isMTFHSupplyInside &&
|
|
!isMTFLDemandInside)
|
|
{
|
|
demandZone = mtfState.demandZones[lDemandIDX];
|
|
}
|
|
else if (!isMTFHSupplyInside &&
|
|
isMTFLDemandInside)
|
|
{
|
|
supplyZone = mtfState.supplyZones[hSupplyIDX];
|
|
}
|
|
else if (isMTFHSupplyInside &&
|
|
isMTFLDemandInside)
|
|
{
|
|
//
|
|
supplyZone = mtfState.supplyZones[hSupplyIDX];
|
|
demandZone = mtfState.demandZones[lDemandIDX];
|
|
}
|
|
|
|
//
|
|
// Check Zones Validation ...
|
|
bool hasTrend =
|
|
supplyZone != NULL &&
|
|
supplyZone.IsValid() &&
|
|
demandZone != NULL &&
|
|
demandZone.IsValid();
|
|
result = hasTrend;
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
datetime from = MathMax(
|
|
supplyZone.From(),
|
|
demandZone.From());
|
|
|
|
//
|
|
int fromIndex = iBarShift(
|
|
symbol,
|
|
period,
|
|
from //
|
|
);
|
|
|
|
//
|
|
// Detect Trend ...
|
|
ENUM_X_DIRECTION trend = X_DIRECTION_NONE;
|
|
datetime supplyTouch = NULL;
|
|
datetime demandTouch = NULL;
|
|
for (int i = zIndex; i < fromIndex; i++)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool isInited = iBar.Init(
|
|
symbol,
|
|
period,
|
|
i //
|
|
);
|
|
if (!isInited)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isTouchSupplyZone =
|
|
//
|
|
iBar.low < supplyZone.Lower() &&
|
|
iBar.GetUp() > supplyZone.Lower()
|
|
//
|
|
;
|
|
if (isTouchSupplyZone &&
|
|
!IsValid(supplyTouch))
|
|
{
|
|
supplyTouch = iBar.time;
|
|
}
|
|
|
|
//
|
|
bool isTouchDemandZone =
|
|
//
|
|
iBar.high > demandZone.Upper() &&
|
|
iBar.GetDown() < demandZone.Upper()
|
|
//
|
|
;
|
|
if (isTouchDemandZone &&
|
|
!IsValid(demandTouch))
|
|
{
|
|
demandTouch = iBar.time;
|
|
}
|
|
|
|
//
|
|
bool canBreak =
|
|
IsValid(supplyTouch) &&
|
|
IsValid(demandTouch);
|
|
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
if (canBreak)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
hasTrend =
|
|
//
|
|
IsValid(supplyTouch) &&
|
|
IsValid(demandTouch)
|
|
//
|
|
;
|
|
if (hasTrend)
|
|
{
|
|
//
|
|
trend =
|
|
//
|
|
supplyTouch > demandTouch
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_BULLISH
|
|
//
|
|
;
|
|
}
|
|
|
|
//
|
|
// Check Trend ...
|
|
result = hasTrend;
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool hasBullishTrend = IsBullish(trend);
|
|
bool hasBearishTrend = IsBearish(trend);
|
|
|
|
//
|
|
// Find Order Block and FVG for Trend Approve ...
|
|
|
|
//
|
|
// Now We Have to Detect at least One OrderBlock with FVG ...
|
|
// for Trend Approvement ...
|
|
bool hasOrderBlock = HasOrderBlock();
|
|
bool hasFairValueGap = HasFairValueGap();
|
|
if (!hasOrderBlock &&
|
|
!hasFairValueGap)
|
|
{
|
|
//
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
XCFVG *fvg = NULL;
|
|
XCOrderBlock *ob = NULL;
|
|
|
|
//
|
|
if (hasBullishTrend)
|
|
{
|
|
//
|
|
has = mtfState.HasBullishOrderBlocks();
|
|
count = mtfState.CountBullishOrderBlocks();
|
|
|
|
//
|
|
if (has)
|
|
{
|
|
//
|
|
// Check Order Block ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCOrderBlock *iOB = mtfState.bullishOrderBlocks[i];
|
|
|
|
//
|
|
iOB.To(cTime);
|
|
|
|
//
|
|
// Check From Passes ...
|
|
bool isFromPassed = iOB.From() > demandZone.From();
|
|
if (!isFromPassed)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Must inside DemandZone ...
|
|
bool isInsideDemand = IsInsideDiff(
|
|
iOB,
|
|
demandZone //
|
|
);
|
|
if (!isInsideDemand)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Started ...
|
|
XOHCL startedBar;
|
|
ENUM_X_DIRECTION startedDir;
|
|
bool isStarted = iOB.IsStarted(
|
|
X_DIRECTION_BULLISH,
|
|
startedBar,
|
|
startedDir //
|
|
);
|
|
if (!isStarted)
|
|
{
|
|
//
|
|
startedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Converts to Box ...
|
|
XBoxZone obBox;
|
|
bool hasOBBox = ToBox(
|
|
obBox,
|
|
iOB //
|
|
);
|
|
if (!hasOBBox)
|
|
{
|
|
//
|
|
obBox.Clean();
|
|
startedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Zone Must not Used before ...
|
|
bool isUsed = IsBoxUsed(
|
|
obBox,
|
|
startedBar.Index() - 1,
|
|
zIndex //
|
|
);
|
|
if (isUsed)
|
|
{
|
|
//
|
|
obBox.Clean();
|
|
startedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ob = iOB;
|
|
|
|
//
|
|
obBox.Clean();
|
|
startedBar.Clean();
|
|
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Detect Fair Value Gap ...
|
|
if (ob != NULL &&
|
|
ob.IsValid())
|
|
{
|
|
//
|
|
has = stfState.HasBullishFairValueGaps();
|
|
count = stfState.CountBullishFairValueGaps();
|
|
if (has)
|
|
{
|
|
//
|
|
// Check Fir Value Gap ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCFVG *iFVG = stfState.bullishFairValueGaps[i];
|
|
|
|
//
|
|
iFVG.To(cTime);
|
|
|
|
//
|
|
// Check From Passes ...
|
|
bool isFromPassed = iFVG.From() > ob.From();
|
|
if (!isFromPassed)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Started ...
|
|
XOHCL startedBar;
|
|
ENUM_X_DIRECTION startedDir;
|
|
bool isStarted = iFVG.IsStarted(
|
|
X_DIRECTION_BULLISH,
|
|
startedBar,
|
|
startedDir //
|
|
);
|
|
if (!isStarted)
|
|
{
|
|
//
|
|
startedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Converts to Box ...
|
|
XBoxZone fvgBox;
|
|
bool hasFVGBox = ToBox(
|
|
fvgBox,
|
|
iFVG //
|
|
);
|
|
if (!hasFVGBox)
|
|
{
|
|
//
|
|
fvgBox.Clean();
|
|
startedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Inside Order Block ...
|
|
bool isInside = IsInsideDiff(
|
|
iFVG,
|
|
ob,
|
|
true // Force Side Out ...
|
|
);
|
|
if (!isInside)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
fvg = iFVG;
|
|
|
|
//
|
|
fvgBox.Clean();
|
|
startedBar.Clean();
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
ob = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (hasBearishTrend)
|
|
{
|
|
//
|
|
has = mtfState.HasBearishOrderBlocks();
|
|
count = mtfState.CountBearishOrderBlocks();
|
|
|
|
//
|
|
if (has)
|
|
{
|
|
//
|
|
// Check Order Block ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCOrderBlock *iOB = mtfState.bearishOrderBlocks[i];
|
|
|
|
//
|
|
iOB.To(cTime);
|
|
|
|
//
|
|
// Check From Passes ...
|
|
bool isFromPassed = iOB.From() > supplyZone.From();
|
|
if (!isFromPassed)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Must inside DemandZone ...
|
|
bool isInsideDemand = IsInsideDiff(
|
|
iOB,
|
|
supplyZone //
|
|
);
|
|
if (!isInsideDemand)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Started ...
|
|
XOHCL startedBar;
|
|
ENUM_X_DIRECTION startedDir;
|
|
bool isStarted = iOB.IsStarted(
|
|
X_DIRECTION_BEARISH,
|
|
startedBar,
|
|
startedDir //
|
|
);
|
|
if (!isStarted)
|
|
{
|
|
//
|
|
startedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Converts to Box ...
|
|
XBoxZone obBox;
|
|
bool hasOBBox = ToBox(
|
|
obBox,
|
|
iOB //
|
|
);
|
|
if (!hasOBBox)
|
|
{
|
|
//
|
|
obBox.Clean();
|
|
startedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Zone Must not Used before ...
|
|
bool isUsed = IsBoxUsed(
|
|
obBox,
|
|
startedBar.Index() - 1,
|
|
zIndex //
|
|
);
|
|
if (isUsed)
|
|
{
|
|
//
|
|
obBox.Clean();
|
|
startedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
ob = iOB;
|
|
|
|
//
|
|
obBox.Clean();
|
|
startedBar.Clean();
|
|
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Detect Fair Value Gap ...
|
|
if (ob != NULL &&
|
|
ob.IsValid())
|
|
{
|
|
//
|
|
has = stfState.HasBearishFairValueGaps();
|
|
count = stfState.CountBearishFairValueGaps();
|
|
if (has)
|
|
{
|
|
//
|
|
// Check Fir Value Gap ...
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCFVG *iFVG = stfState.bearishFairValueGaps[i];
|
|
|
|
//
|
|
iFVG.To(cTime);
|
|
|
|
//
|
|
// Check From Passes ...
|
|
bool isFromPassed = iFVG.From() > ob.From();
|
|
if (!isFromPassed)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Started ...
|
|
XOHCL startedBar;
|
|
ENUM_X_DIRECTION startedDir;
|
|
bool isStarted = iFVG.IsStarted(
|
|
X_DIRECTION_BEARISH,
|
|
startedBar,
|
|
startedDir //
|
|
);
|
|
if (!isStarted)
|
|
{
|
|
//
|
|
startedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Converts to Box ...
|
|
XBoxZone fvgBox;
|
|
bool hasFVGBox = ToBox(
|
|
fvgBox,
|
|
iFVG //
|
|
);
|
|
if (!hasFVGBox)
|
|
{
|
|
//
|
|
fvgBox.Clean();
|
|
startedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Inside Order Block ...
|
|
bool isInside = IsInsideDiff(
|
|
iFVG,
|
|
ob,
|
|
true // Force Side Out ...
|
|
);
|
|
if (!isInside)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
fvg = iFVG;
|
|
|
|
//
|
|
fvgBox.Clean();
|
|
startedBar.Clean();
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
ob = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (ob != NULL &&
|
|
fvg != NULL)
|
|
{
|
|
//
|
|
orderBlock = ob;
|
|
fairValueGap = fvg;
|
|
}
|
|
|
|
//
|
|
hasOrderBlock = HasOrderBlock();
|
|
hasFairValueGap = HasFairValueGap();
|
|
}
|
|
|
|
//
|
|
// Check Trend Approved ...
|
|
bool isTrendApproved =
|
|
hasOrderBlock &&
|
|
hasFairValueGap;
|
|
result = isTrendApproved;
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean();
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Prepare Working Zone ...
|
|
workingZone.symbol = symbol;
|
|
workingZone.period = period;
|
|
|
|
//
|
|
workingZone.upper = supplyZone.Lower();
|
|
workingZone.zoneUpper = supplyZone.Upper();
|
|
|
|
//
|
|
workingZone.lower = demandZone.Upper();
|
|
workingZone.zoneLower = demandZone.Lower();
|
|
|
|
//
|
|
workingZone.from = from;
|
|
|
|
//
|
|
double upper = workingZone.upper;
|
|
double range =
|
|
workingZone.upper - workingZone.lower;
|
|
double ranegPercent = range / 100;
|
|
double quarterValue = ranegPercent * 25;
|
|
|
|
//
|
|
workingZone.quarter1 = upper - (quarterValue * 1);
|
|
workingZone.quarter2 = upper - (quarterValue * 2);
|
|
workingZone.quarter3 = upper - (quarterValue * 3);
|
|
|
|
//
|
|
result = workingZone.IsValid();
|
|
if (!result)
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool IsWorkingZoneDestroyed(
|
|
ENUM_X_DIRECTION &destroyedDir,
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
destroyedDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = workingZone.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = workingZone.IsDestroyed(
|
|
destroyedDir,
|
|
barIndex,
|
|
forPeriod //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool DetectTrend(
|
|
ENUM_X_DIRECTION &trend,
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (forPeriod == NULL)
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
trend = X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = HasWorkingZone();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int FromIndex = iBarShift(
|
|
symbol,
|
|
forPeriod,
|
|
workingZone.from //
|
|
);
|
|
|
|
//
|
|
datetime supplyTouch = NULL;
|
|
datetime demandTouch = NULL;
|
|
for (int i = barIndex; i < FromIndex; i++)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool isInited = iBar.Init(
|
|
symbol,
|
|
forPeriod,
|
|
i //
|
|
);
|
|
if (!isInited)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isTouchSupplyZone =
|
|
//
|
|
iBar.low < supplyZone.Lower() &&
|
|
iBar.GetUp() > supplyZone.Lower()
|
|
//
|
|
;
|
|
if (isTouchSupplyZone &&
|
|
!IsValid(supplyTouch))
|
|
{
|
|
supplyTouch = iBar.time;
|
|
}
|
|
|
|
//
|
|
bool isTouchDemandZone =
|
|
//
|
|
iBar.high > demandZone.Upper() &&
|
|
iBar.GetDown() < demandZone.Upper()
|
|
//
|
|
;
|
|
if (isTouchDemandZone &&
|
|
!IsValid(demandTouch))
|
|
{
|
|
demandTouch = iBar.time;
|
|
}
|
|
|
|
//
|
|
bool canBreak =
|
|
IsValid(supplyTouch) &&
|
|
IsValid(demandTouch);
|
|
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
if (canBreak)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(supplyTouch) &&
|
|
IsValid(demandTouch)
|
|
//
|
|
;
|
|
if (result)
|
|
{
|
|
//
|
|
trend =
|
|
//
|
|
supplyTouch > demandTouch
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_BULLISH
|
|
//
|
|
;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool DetectStartZone(
|
|
ENUM_X_DIRECTION forDir,
|
|
XPOIState &state,
|
|
XC121SMCCycleHelper *cycleHelper //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = state.IsValid() &&
|
|
state.HasChild() &&
|
|
HasDirection(forDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
int idx = -1;
|
|
int count = 0;
|
|
int has = false;
|
|
|
|
//
|
|
bool hasBullishCZone = false;
|
|
bool hasBearishCZone = false;
|
|
|
|
//
|
|
// Supply Zones ...
|
|
has = state.HasSupplyZones();
|
|
if (has)
|
|
{
|
|
//
|
|
idx = GetYoungest(state.supplyZones);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
startZone.supply = state.supplyZones[idx];
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand Zones ...
|
|
has = state.HasDemandZones();
|
|
if (has)
|
|
{
|
|
//
|
|
idx = GetYoungest(state.demandZones);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
startZone.demand = state.demandZones[idx];
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support Zones ...
|
|
has = state.HasSupportZones();
|
|
if (has)
|
|
{
|
|
//
|
|
idx = GetYoungest(state.supportZones);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
startZone.support = state.supportZones[idx];
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistance Zones ...
|
|
has = state.HasResistanceZones();
|
|
if (has)
|
|
{
|
|
//
|
|
idx = GetYoungest(state.resistanceZones);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
startZone.resistance = state.resistanceZones[idx];
|
|
}
|
|
}
|
|
|
|
//
|
|
// Consolidation Zones ...
|
|
has = cycleHelper.HasConsolidationZones();
|
|
if (has)
|
|
{
|
|
//
|
|
hasBullishCZone = cycleHelper
|
|
.GetLastDirectionalConsolidationZone(
|
|
X_DIRECTION_BULLISH,
|
|
startZone.bullishConsolidationZone //
|
|
);
|
|
|
|
//
|
|
hasBearishCZone = cycleHelper
|
|
.GetLastDirectionalConsolidationZone(
|
|
X_DIRECTION_BEARISH,
|
|
startZone.bearishConsolidationZone //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Other Zones ...
|
|
if (isBullish)
|
|
{
|
|
//
|
|
// Order Block ...
|
|
has = state.HasBullishOrderBlocks();
|
|
if (has)
|
|
{
|
|
//
|
|
idx = GetYoungest(state.bullishOrderBlocks);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
startZone.ob = state.bullishOrderBlocks[idx];
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gap ...
|
|
has = state.HasBullishFairValueGaps();
|
|
if (has)
|
|
{
|
|
//
|
|
idx = GetYoungest(state.bullishFairValueGaps);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
startZone.fvg = state.bullishFairValueGaps[idx];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Order Block ...
|
|
has = state.HasBearishOrderBlocks();
|
|
if (has)
|
|
{
|
|
//
|
|
idx = GetYoungest(state.bearishOrderBlocks);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
startZone.ob = state.bearishOrderBlocks[idx];
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gap ...
|
|
has = state.HasBearishFairValueGaps();
|
|
if (has)
|
|
{
|
|
//
|
|
idx = GetYoungest(state.bearishFairValueGaps);
|
|
if (IsValidIndex(idx))
|
|
{
|
|
startZone.fvg = state.bearishFairValueGaps[idx];
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
bool hasOBFVG = startZone.HasOB() &&
|
|
startZone.HasFVG();
|
|
bool isOBInsideFVG = false;
|
|
bool isFVGInsideOB = false;
|
|
if (hasOBFVG)
|
|
{
|
|
//
|
|
isOBInsideFVG =
|
|
IsInsideDiff(
|
|
startZone.ob,
|
|
startZone.fvg //
|
|
) ||
|
|
(isBullish
|
|
? IsAboveDiff(
|
|
startZone.ob,
|
|
startZone.fvg,
|
|
true // IgnoreInside
|
|
)
|
|
: IsBelowDiff(
|
|
startZone.ob,
|
|
startZone.fvg,
|
|
true // IgnoreInside
|
|
));
|
|
//
|
|
isFVGInsideOB =
|
|
IsInsideDiff(
|
|
startZone.fvg,
|
|
startZone.ob //
|
|
) ||
|
|
(isBullish
|
|
? IsAboveDiff(
|
|
startZone.fvg,
|
|
startZone.ob,
|
|
true // IgnoreInside
|
|
)
|
|
: IsBelowDiff(
|
|
startZone.fvg,
|
|
startZone.ob,
|
|
true // IgnoreInside
|
|
));
|
|
}
|
|
|
|
//
|
|
result =
|
|
startZone.IsValid() &&
|
|
(isOBInsideFVG ||
|
|
isFVGInsideOB) &&
|
|
(isBullish
|
|
? startZone.IsBullish()
|
|
: startZone.IsBearish());
|
|
if (!result)
|
|
{
|
|
//
|
|
startZone.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void DetectPriority(
|
|
ENUM_X121SMC_XWZ_PRIORITY &bullish,
|
|
ENUM_X121SMC_XWZ_PRIORITY &bearish,
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bullish = X121SMC_XWZ_PRIORITY_NONE;
|
|
bearish = X121SMC_XWZ_PRIORITY_NONE;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
bool hasWorkingZone = HasWorkingZone();
|
|
if (!hasWorkingZone)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
XOHCL zBar;
|
|
bool isInited = zBar.Init(
|
|
symbol,
|
|
forPeriod,
|
|
barIndex //
|
|
);
|
|
if (!isInited)
|
|
{
|
|
//
|
|
zBar.Clean();
|
|
return;
|
|
}
|
|
|
|
//
|
|
XOHCL cBar;
|
|
isInited = zBar.GetPreviousBar(cBar);
|
|
if (!isInited)
|
|
{
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// ZoneUpper, Upper ...
|
|
if (cBar.low > workingZone.upper &&
|
|
cBar.high < workingZone.zoneUpper &&
|
|
zBar.low > workingZone.upper &&
|
|
zBar.high < workingZone.zoneUpper)
|
|
{
|
|
//
|
|
bullish = X121SMC_XWZ_PRIORITY_NONE;
|
|
bearish = X121SMC_XWZ_PRIORITY_STRONG_HIGH;
|
|
}
|
|
//
|
|
// Upper, Quarter1 ...
|
|
else if (cBar.low > workingZone.quarter1 &&
|
|
cBar.high < workingZone.upper &&
|
|
zBar.low > workingZone.quarter1 &&
|
|
zBar.high < workingZone.upper)
|
|
{
|
|
//
|
|
bullish = X121SMC_XWZ_PRIORITY_WEAK;
|
|
bearish = X121SMC_XWZ_PRIORITY_HIGH;
|
|
}
|
|
//
|
|
// Quarter1, Quarter2 ...
|
|
else if (cBar.low > workingZone.quarter2 &&
|
|
cBar.high < workingZone.quarter1 &&
|
|
zBar.low > workingZone.quarter2 &&
|
|
zBar.high < workingZone.quarter1)
|
|
{
|
|
//
|
|
bullish = X121SMC_XWZ_PRIORITY_LOW;
|
|
bearish = X121SMC_XWZ_PRIORITY_REGULAR;
|
|
}
|
|
//
|
|
// Quarter2, Quarter3 ...
|
|
else if (cBar.low > workingZone.quarter3 &&
|
|
cBar.high < workingZone.quarter2 &&
|
|
zBar.low > workingZone.quarter3 &&
|
|
zBar.high < workingZone.quarter2)
|
|
{
|
|
//
|
|
bullish = X121SMC_XWZ_PRIORITY_REGULAR;
|
|
bearish = X121SMC_XWZ_PRIORITY_LOW;
|
|
}
|
|
//
|
|
// Quarter3, Lower ...
|
|
else if (cBar.low > workingZone.lower &&
|
|
cBar.high < workingZone.quarter3 &&
|
|
zBar.low > workingZone.lower &&
|
|
zBar.high < workingZone.quarter3)
|
|
{
|
|
//
|
|
bullish = X121SMC_XWZ_PRIORITY_HIGH;
|
|
bearish = X121SMC_XWZ_PRIORITY_WEAK;
|
|
}
|
|
//
|
|
// Lower, ZoneLower ...
|
|
else if (cBar.low > workingZone.zoneLower &&
|
|
cBar.high < workingZone.lower &&
|
|
zBar.low > workingZone.zoneLower &&
|
|
zBar.high < workingZone.lower)
|
|
{
|
|
//
|
|
bullish = X121SMC_XWZ_PRIORITY_STRONG_HIGH;
|
|
bearish = X121SMC_XWZ_PRIORITY_NONE;
|
|
}
|
|
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
}
|
|
|
|
//
|
|
double GetEntry()
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
if (!IsValid(symbol) ||
|
|
!HasDirection(dir))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetEntry(
|
|
symbol,
|
|
dir //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double GetSpread()
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
if (!IsValid(symbol))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetSpread(
|
|
symbol //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double GetPoint()
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
if (!IsValid(symbol) ||
|
|
!HasDirection(dir) ||
|
|
!HasStartZone())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(dir);
|
|
XBoxZone asBox;
|
|
bool hasBox = startZone.AsBox(asBox);
|
|
if (!hasBox)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
isBullish
|
|
? asBox.upper
|
|
: asBox.lower;
|
|
|
|
//
|
|
asBox.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double GetExit()
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
if (!IsValid(symbol) ||
|
|
!HasDirection(dir) ||
|
|
!HasStartZone())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(dir);
|
|
XBoxZone asBox;
|
|
bool hasBox = startZone.AsBox(asBox);
|
|
if (!hasBox)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
isBullish
|
|
? asBox.lower
|
|
: asBox.upper;
|
|
|
|
//
|
|
asBox.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|