3560 lines
85 KiB
Plaintext
3560 lines
85 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;
|
|
|
|
//
|
|
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();
|
|
}
|
|
|
|
//
|
|
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 IsBullish()
|
|
{
|
|
//
|
|
return HasOB() &&
|
|
ob.IsBullish() &&
|
|
HasFVG() &&
|
|
fvg.IsBullish();
|
|
}
|
|
|
|
//
|
|
bool IsBearish()
|
|
{
|
|
//
|
|
return HasOB() &&
|
|
ob.IsBearish() &&
|
|
HasFVG() &&
|
|
fvg.IsBearish();
|
|
}
|
|
|
|
//
|
|
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 IsPriceInside(
|
|
XBoxZone &box,
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL,
|
|
bool forceOB = false,
|
|
bool forceFVG = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
result = IsValid() &&
|
|
HasOB() &&
|
|
HasFVG() &&
|
|
HasDirection();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string symbol = ob.GetSymbol();
|
|
if (forPeriod == NULL)
|
|
{
|
|
forPeriod = ob.GetPeriod();
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION forDir = ob.GetDirection();
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
// Check Start Bars ...
|
|
|
|
//
|
|
XOHCL obStartedBar;
|
|
ENUM_X_DIRECTION obStartedDir;
|
|
bool isOBStarted = ob.IsStarted(
|
|
forDir,
|
|
obStartedBar,
|
|
obStartedDir //
|
|
);
|
|
result = isOBStarted;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL fvgStartedBar;
|
|
ENUM_X_DIRECTION fvgStartedDir;
|
|
bool isFVGStarted = fvg.IsStarted(
|
|
forDir,
|
|
fvgStartedBar,
|
|
fvgStartedDir //
|
|
);
|
|
result = isFVGStarted;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Bars ...
|
|
|
|
//
|
|
XOHCL zBar;
|
|
result = zBar.Init(
|
|
symbol,
|
|
forPeriod,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
zBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL cBar;
|
|
result = zBar.GetPreviousBar(cBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL pBar;
|
|
result = cBar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
box.Clean();
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isPriceInsideOB = X121SMCXWZCheckPriceInside(
|
|
zBar,
|
|
cBar,
|
|
ob.Upper(),
|
|
ob.Lower() //
|
|
);
|
|
|
|
//
|
|
// isBullish
|
|
// ? (
|
|
// //
|
|
// pBar.close > ob.Upper() &&
|
|
// cBar.low <= ob.Upper() &&
|
|
// cBar.close <= ob.Upper() &&
|
|
// zBar.open <= ob.Upper()
|
|
// //
|
|
// )
|
|
// : (
|
|
// //
|
|
// pBar.close < ob.Lower() &&
|
|
// cBar.high >= ob.Lower() &&
|
|
// cBar.close >= ob.Lower() &&
|
|
// zBar.open >= ob.Lower()
|
|
// //
|
|
// );
|
|
|
|
//
|
|
bool isPriceInsideFVG = X121SMCXWZCheckPriceInside(
|
|
zBar,
|
|
cBar,
|
|
fvg.Upper(),
|
|
fvg.Lower() //
|
|
);
|
|
|
|
//
|
|
// isBullish
|
|
// ? (
|
|
// //
|
|
// pBar.close > fvg.Upper() &&
|
|
// cBar.low <= fvg.Upper() &&
|
|
// cBar.close <= fvg.Upper() &&
|
|
// zBar.open <= fvg.Upper()
|
|
// //
|
|
// )
|
|
// : (
|
|
// //
|
|
// pBar.close < fvg.Lower() &&
|
|
// cBar.high >= fvg.Lower() &&
|
|
// cBar.close >= fvg.Lower() &&
|
|
// zBar.open >= fvg.Lower()
|
|
// //
|
|
// );
|
|
|
|
//
|
|
if ((forceOB && forceFVG) ||
|
|
(!forceOB && !forceFVG))
|
|
{
|
|
//
|
|
result =
|
|
isPriceInsideOB ||
|
|
isPriceInsideFVG;
|
|
}
|
|
else if (forceOB)
|
|
{
|
|
result = isPriceInsideOB;
|
|
}
|
|
else if (forceFVG)
|
|
{
|
|
result = isPriceInsideFVG;
|
|
}
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
if (isPriceInsideOB && !isPriceInsideFVG)
|
|
{
|
|
//
|
|
result = ToBox(
|
|
box,
|
|
ob //
|
|
);
|
|
}
|
|
else if (isPriceInsideFVG && !isPriceInsideOB)
|
|
{
|
|
//
|
|
result = ToBox(
|
|
box,
|
|
fvg //
|
|
);
|
|
}
|
|
else if (isPriceInsideOB && isPriceInsideFVG)
|
|
{
|
|
result = AsBox(box);
|
|
}
|
|
}
|
|
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasInsideConditions(
|
|
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();
|
|
|
|
//
|
|
XBoxZone zoneBox;
|
|
bool hasBox = AsBox(zoneBox);
|
|
|
|
//
|
|
result = hasBox &&
|
|
IsValid() &&
|
|
HasDirection() &&
|
|
state.IsValid() &&
|
|
state.HasChild();
|
|
if (!result)
|
|
{
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string symbol = zoneBox.symbol;
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = zoneBox.period;
|
|
}
|
|
datetime cTime = iTime(
|
|
symbol,
|
|
forPeriod,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
ENUM_X_DIRECTION forDir = zoneBox.dir;
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
XBoxZone supResBoxes[];
|
|
int supresBoxesCount = 0;
|
|
bool hasSupResBoxes = 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,
|
|
zoneBox //
|
|
);
|
|
if (!isInside)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
supResBoxes //
|
|
);
|
|
|
|
//
|
|
iBox.Clean();
|
|
ZeroMemory(iZone);
|
|
}
|
|
|
|
//
|
|
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,
|
|
zoneBox //
|
|
);
|
|
if (!isInside)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
supResBoxes //
|
|
);
|
|
|
|
//
|
|
iBox.Clean();
|
|
ZeroMemory(iZone);
|
|
}
|
|
|
|
//
|
|
supresBoxesCount = ArraySize(supResBoxes);
|
|
hasSupResBoxes = IsValidSize(supresBoxesCount);
|
|
}
|
|
|
|
//
|
|
result = hasSupResBoxes;
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean(supResBoxes);
|
|
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < supresBoxesCount; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = supResBoxes[i];
|
|
|
|
//
|
|
bool hasBoxConditions = HasBoxConitions(
|
|
iBox,
|
|
state,
|
|
barIndex,
|
|
forPeriod //
|
|
);
|
|
if (hasBoxConditions)
|
|
{
|
|
//
|
|
appliedBox = iBox;
|
|
result = true;
|
|
iBox.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
}
|
|
|
|
//
|
|
Clean(supResBoxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool HasBoxConitions(
|
|
XBoxZone &box,
|
|
XPOIState &state,
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
result = box.IsValid() &&
|
|
IsValid() &&
|
|
HasDirection();
|
|
if (!result)
|
|
{
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string symbol = box.symbol;
|
|
if (forPeriod == NULL)
|
|
{
|
|
forPeriod = box.period;
|
|
}
|
|
ENUM_X_DIRECTION forDir = box.dir;
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
// Detect Bars ...
|
|
|
|
//
|
|
XOHCL zBar;
|
|
result = zBar.Init(
|
|
symbol,
|
|
forPeriod,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
zBar.Clean();
|
|
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL cBar;
|
|
result = zBar.GetPreviousBar(cBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL pBar;
|
|
result = cBar.GetPreviousBar(pBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL ppBar;
|
|
result = pBar.GetPreviousBar(ppBar);
|
|
if (!result)
|
|
{
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
ppBar.Clean();
|
|
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
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();
|
|
|
|
//
|
|
double appliedPrice =
|
|
isBullish
|
|
? box.upper
|
|
: box.lower;
|
|
|
|
//
|
|
// 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;
|
|
|
|
//
|
|
result =
|
|
//
|
|
isBoxBreaked ||
|
|
isBoxRejected ||
|
|
hasValidPressuredSwing
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
}
|
|
else
|
|
{
|
|
appliedBox = box;
|
|
}
|
|
|
|
//
|
|
zBar.Clean();
|
|
cBar.Clean();
|
|
pBar.Clean();
|
|
ppBar.Clean();
|
|
|
|
//
|
|
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;
|
|
|
|
//
|
|
XOHCL swingBar;
|
|
XOHCL breakerBar;
|
|
XOHCL momentumBar;
|
|
XOHCL rejectionBar;
|
|
XBoxZone appliedBox;
|
|
|
|
//
|
|
X121SMCXWZWorkingZone()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
void Clean()
|
|
{
|
|
//
|
|
upper = 0;
|
|
lower = 0;
|
|
quarter1 = 0;
|
|
quarter2 = 0;
|
|
quarter3 = 0;
|
|
zoneLower = 0;
|
|
zoneUpper = 0;
|
|
|
|
//
|
|
from = NULL;
|
|
symbol = NULL;
|
|
period = NULL;
|
|
|
|
//
|
|
CleanConditionBars();
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
//
|
|
void CleanConditionBars()
|
|
{
|
|
//
|
|
swingBar.Clean();
|
|
breakerBar.Clean();
|
|
appliedBox.Clean();
|
|
momentumBar.Clean();
|
|
rejectionBar.Clean();
|
|
}
|
|
|
|
//
|
|
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 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;
|
|
X121SMCXWZZone startZones[];
|
|
|
|
//
|
|
// 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();
|
|
Clean(startZones);
|
|
|
|
//
|
|
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 HasStartZones()
|
|
{
|
|
return HasChild(startZones);
|
|
}
|
|
|
|
//
|
|
int CountStartZones()
|
|
{
|
|
return ArraySize(startZones);
|
|
}
|
|
|
|
//
|
|
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 hasStartZones = HasStartZones();
|
|
if (hasStartZones)
|
|
{
|
|
//
|
|
int count = CountStartZones();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
bool hasOB = startZones[i].HasOB();
|
|
if (hasOB)
|
|
{
|
|
startZones[i].ob.To(value);
|
|
}
|
|
|
|
//
|
|
bool hasFVG = startZones[i].HasFVG();
|
|
if (hasFVG)
|
|
{
|
|
startZones[i].fvg.To(value);
|
|
}
|
|
|
|
//
|
|
bool hasSupply = startZones[i].HasSupply();
|
|
if (hasSupply)
|
|
{
|
|
startZones[i].supply.To(value);
|
|
}
|
|
|
|
//
|
|
bool hasDemand = startZones[i].HasDemand();
|
|
if (hasDemand)
|
|
{
|
|
startZones[i].demand.To(value);
|
|
}
|
|
|
|
//
|
|
bool hasSupport = startZones[i].HasSupport();
|
|
if (hasSupport)
|
|
{
|
|
startZones[i].support.To(value);
|
|
}
|
|
|
|
//
|
|
bool hasResistance = startZones[i].HasResistance();
|
|
if (hasResistance)
|
|
{
|
|
startZones[i].resistance.To(value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
//
|
|
// 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 ...
|
|
|
|
//
|
|
bool isBullishTrendApproved = false;
|
|
bool isBearishTrendApproved = false;
|
|
|
|
//
|
|
// 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;
|
|
|
|
//
|
|
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;
|
|
}
|
|
}
|
|
|
|
//
|
|
if (ob != NULL &&
|
|
fvg != NULL)
|
|
{
|
|
//
|
|
orderBlock = ob;
|
|
fairValueGap = fvg;
|
|
}
|
|
|
|
//
|
|
hasOrderBlock = HasOrderBlock();
|
|
hasFairValueGap = HasFairValueGap();
|
|
isBullishTrendApproved = hasOrderBlock &&
|
|
hasFairValueGap;
|
|
}
|
|
|
|
//
|
|
if (!isBullishTrendApproved)
|
|
{
|
|
//
|
|
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();
|
|
isBearishTrendApproved = hasOrderBlock &&
|
|
hasFairValueGap;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Trend Approved ...
|
|
bool isTrendApproved =
|
|
hasOrderBlock &&
|
|
hasFairValueGap &&
|
|
(isBullishTrendApproved ||
|
|
isBearishTrendApproved);
|
|
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 DetectStartZones(
|
|
ENUM_X_DIRECTION forDir,
|
|
XPOIState &obState,
|
|
XPOIState &fvgState,
|
|
XPOIState &otherState,
|
|
XC121SMCCycleHelper *cycleHelper //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = obState.IsValid() &&
|
|
obState.HasChild() &&
|
|
fvgState.IsValid() &&
|
|
fvgState.HasChild() &&
|
|
otherState.IsValid() &&
|
|
otherState.HasChild() &&
|
|
HasDirection(forDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
int idx = -1;
|
|
int count = 0;
|
|
int has = false;
|
|
|
|
//
|
|
X121SMCXWZZone startZone;
|
|
X121SMCXWZZone lastStartZone;
|
|
bool hasLastStartZone = HasStartZones();
|
|
if (hasLastStartZone)
|
|
{
|
|
//
|
|
int startZonesCount = CountStartZones();
|
|
lastStartZone = startZones[startZonesCount - 1];
|
|
}
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
has = obState.HasBullishOrderBlocks();
|
|
if (has)
|
|
{
|
|
//
|
|
count = obState.CountBullishOrderBlocks();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCOrderBlock *iOB = obState.bullishOrderBlocks[i];
|
|
|
|
//
|
|
bool isFromPassed =
|
|
!hasLastStartZone
|
|
? true
|
|
: iOB.From() > lastStartZone.ob.From();
|
|
if (!isFromPassed)
|
|
{
|
|
//
|
|
ZeroMemory(iOB);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
XOHCL startedBar;
|
|
ENUM_X_DIRECTION startedDir;
|
|
bool isStarted = iOB.IsStarted(
|
|
forDir,
|
|
startedBar,
|
|
startedDir //
|
|
);
|
|
if (!isStarted)
|
|
{
|
|
//
|
|
ZeroMemory(iOB);
|
|
startedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
XOHCL activatedBar;
|
|
ENUM_X_DIRECTION activatedDir;
|
|
bool isActivated = iOB.IsActivated(
|
|
forDir,
|
|
activatedBar,
|
|
activatedDir //
|
|
);
|
|
if (isActivated)
|
|
{
|
|
//
|
|
ZeroMemory(iOB);
|
|
startedBar.Clean();
|
|
activatedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isPlacePassed =
|
|
!IsInsideDiff(
|
|
iOB,
|
|
demandZone //
|
|
) &&
|
|
(!hasLastStartZone
|
|
? workingZone.IsValid() &&
|
|
HasOrderBlock() &&
|
|
forDir == orderBlock.GetDirection()
|
|
? IsAbove(
|
|
iOB,
|
|
orderBlock,
|
|
true // Ignore Inside ...
|
|
)
|
|
: true
|
|
: lastStartZone.HasOB() &&
|
|
IsAbove(
|
|
iOB,
|
|
lastStartZone.ob,
|
|
true // Ignore Inside ...
|
|
));
|
|
if (!isPlacePassed)
|
|
{
|
|
//
|
|
ZeroMemory(iOB);
|
|
startedBar.Clean();
|
|
activatedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Attache OB ...
|
|
startZone.ob = iOB;
|
|
|
|
//
|
|
// Now we Have to Find Specified FVG ...
|
|
has = fvgState.HasBullishFairValueGaps();
|
|
if (has)
|
|
{
|
|
//
|
|
int jCount = fvgState.CountBullishFairValueGaps();
|
|
for (int j = 0; j < jCount; j++)
|
|
{
|
|
//
|
|
XCFVG *jFVG = fvgState.bullishFairValueGaps[j];
|
|
|
|
//
|
|
startedBar.Clean();
|
|
startedDir = X_DIRECTION_NONE;
|
|
isStarted = jFVG.IsStarted(
|
|
forDir,
|
|
startedBar,
|
|
startedDir //
|
|
);
|
|
if (!isStarted)
|
|
{
|
|
//
|
|
ZeroMemory(jFVG);
|
|
startedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
activatedBar.Clean();
|
|
activatedDir = X_DIRECTION_NONE;
|
|
isActivated = jFVG.IsActivated(
|
|
forDir,
|
|
activatedBar,
|
|
activatedDir //
|
|
);
|
|
if (isActivated)
|
|
{
|
|
//
|
|
ZeroMemory(jFVG);
|
|
startedBar.Clean();
|
|
activatedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
isPlacePassed =
|
|
//
|
|
!IsInsideDiff(
|
|
jFVG,
|
|
demandZone //
|
|
) &&
|
|
IsAboveDiff(
|
|
jFVG,
|
|
iOB,
|
|
true // Ignore Inside ...
|
|
)
|
|
//
|
|
;
|
|
if (!isPlacePassed)
|
|
{
|
|
//
|
|
ZeroMemory(jFVG);
|
|
startedBar.Clean();
|
|
activatedBar.Clean();
|
|
}
|
|
|
|
//
|
|
startZone.fvg = jFVG;
|
|
}
|
|
}
|
|
|
|
//
|
|
startedBar.Clean();
|
|
activatedBar.Clean();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
has = obState.HasBearishOrderBlocks();
|
|
if (has)
|
|
{
|
|
//
|
|
count = obState.CountBearishOrderBlocks();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCOrderBlock *iOB = obState.bearishOrderBlocks[i];
|
|
|
|
//
|
|
bool isFromPassed =
|
|
!hasLastStartZone
|
|
? true
|
|
: iOB.From() > lastStartZone.ob.From();
|
|
if (!isFromPassed)
|
|
{
|
|
//
|
|
ZeroMemory(iOB);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
XOHCL startedBar;
|
|
ENUM_X_DIRECTION startedDir;
|
|
bool isStarted = iOB.IsStarted(
|
|
forDir,
|
|
startedBar,
|
|
startedDir //
|
|
);
|
|
if (!isStarted)
|
|
{
|
|
//
|
|
ZeroMemory(iOB);
|
|
startedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
XOHCL activatedBar;
|
|
ENUM_X_DIRECTION activatedDir;
|
|
bool isActivated = iOB.IsActivated(
|
|
forDir,
|
|
activatedBar,
|
|
activatedDir //
|
|
);
|
|
if (isActivated)
|
|
{
|
|
//
|
|
ZeroMemory(iOB);
|
|
startedBar.Clean();
|
|
activatedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isPlacePassed =
|
|
!IsInsideDiff(
|
|
iOB,
|
|
supplyZone //
|
|
) &&
|
|
(!hasLastStartZone
|
|
? workingZone.IsValid() &&
|
|
HasOrderBlock() &&
|
|
forDir == orderBlock.GetDirection()
|
|
? IsBelow(
|
|
iOB,
|
|
orderBlock,
|
|
true // Ignore Inside ...
|
|
)
|
|
: true
|
|
: lastStartZone.HasOB() &&
|
|
IsBelow(
|
|
iOB,
|
|
lastStartZone.ob,
|
|
true // Ignore Inside ...
|
|
));
|
|
if (!isPlacePassed)
|
|
{
|
|
//
|
|
ZeroMemory(iOB);
|
|
startedBar.Clean();
|
|
activatedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Attache OB ...
|
|
startZone.ob = iOB;
|
|
|
|
//
|
|
// Now we Have to Find Specified FVG ...
|
|
has = fvgState.HasBearishFairValueGaps();
|
|
if (has)
|
|
{
|
|
//
|
|
int jCount = fvgState.CountBearishFairValueGaps();
|
|
for (int j = 0; j < jCount; j++)
|
|
{
|
|
//
|
|
XCFVG *jFVG = fvgState.bearishFairValueGaps[j];
|
|
|
|
//
|
|
startedBar.Clean();
|
|
startedDir = X_DIRECTION_NONE;
|
|
isStarted = jFVG.IsStarted(
|
|
forDir,
|
|
startedBar,
|
|
startedDir //
|
|
);
|
|
if (!isStarted)
|
|
{
|
|
//
|
|
ZeroMemory(jFVG);
|
|
startedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
activatedBar.Clean();
|
|
activatedDir = X_DIRECTION_NONE;
|
|
isActivated = jFVG.IsActivated(
|
|
forDir,
|
|
activatedBar,
|
|
activatedDir //
|
|
);
|
|
if (isActivated)
|
|
{
|
|
//
|
|
ZeroMemory(jFVG);
|
|
startedBar.Clean();
|
|
activatedBar.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
isPlacePassed =
|
|
//
|
|
!IsInsideDiff(
|
|
jFVG,
|
|
supplyZone //
|
|
) &&
|
|
IsBelowDiff(
|
|
jFVG,
|
|
iOB,
|
|
true // Ignore Inside ...
|
|
)
|
|
//
|
|
;
|
|
if (!isPlacePassed)
|
|
{
|
|
//
|
|
ZeroMemory(jFVG);
|
|
startedBar.Clean();
|
|
activatedBar.Clean();
|
|
}
|
|
|
|
//
|
|
startZone.fvg = jFVG;
|
|
}
|
|
}
|
|
|
|
//
|
|
startedBar.Clean();
|
|
activatedBar.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
bool hasOBFVG = startZone.HasOB() &&
|
|
startZone.HasFVG();
|
|
result = hasOBFVG;
|
|
if (!result)
|
|
{
|
|
//
|
|
startZone.Clean();
|
|
lastStartZone.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone startBox;
|
|
bool hasStartBox = startZone.AsBox(startBox);
|
|
result = hasStartBox;
|
|
if (!result)
|
|
{
|
|
//
|
|
startBox.Clean();
|
|
startZone.Clean();
|
|
lastStartZone.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detect Other Zones Inside Box ...
|
|
XBoxZone tmpBoxes[];
|
|
|
|
//
|
|
// Supply Zones ...
|
|
has = otherState.HasSupplyZones();
|
|
if (has)
|
|
{
|
|
//
|
|
count = ToBox(
|
|
otherState.supplyZones,
|
|
tmpBoxes //
|
|
);
|
|
|
|
//
|
|
has = IsValidSize(count);
|
|
if (has)
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = tmpBoxes[i];
|
|
|
|
//
|
|
bool isPlacePassed =
|
|
//
|
|
IsBoxInside(
|
|
iBox,
|
|
startBox,
|
|
false,
|
|
false //
|
|
)
|
|
//
|
|
;
|
|
if (!isPlacePassed)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
startZone.supply = otherState.supplyZones[i];
|
|
|
|
//
|
|
iBox.Clean();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand Zones ...
|
|
Clean(tmpBoxes);
|
|
has = otherState.HasDemandZones();
|
|
if (has)
|
|
{
|
|
//
|
|
count = ToBox(
|
|
otherState.demandZones,
|
|
tmpBoxes //
|
|
);
|
|
|
|
//
|
|
has = IsValidSize(count);
|
|
if (has)
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = tmpBoxes[i];
|
|
|
|
//
|
|
bool isPlacePassed =
|
|
//
|
|
IsBoxInside(
|
|
iBox,
|
|
startBox,
|
|
false,
|
|
false //
|
|
)
|
|
//
|
|
;
|
|
if (!isPlacePassed)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
startZone.demand = otherState.demandZones[i];
|
|
|
|
//
|
|
iBox.Clean();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support Zones ...
|
|
Clean(tmpBoxes);
|
|
has = otherState.HasSupportZones();
|
|
if (has)
|
|
{
|
|
//
|
|
count = ToBox(
|
|
otherState.supportZones,
|
|
tmpBoxes //
|
|
);
|
|
|
|
//
|
|
has = IsValidSize(count);
|
|
if (has)
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = tmpBoxes[i];
|
|
|
|
//
|
|
bool isPlacePassed =
|
|
//
|
|
IsBoxInside(
|
|
iBox,
|
|
startBox,
|
|
false,
|
|
false //
|
|
)
|
|
//
|
|
;
|
|
if (!isPlacePassed)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
startZone.support = otherState.supportZones[i];
|
|
|
|
//
|
|
iBox.Clean();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistance Zones ...
|
|
Clean(tmpBoxes);
|
|
has = otherState.HasResistanceZones();
|
|
if (has)
|
|
{
|
|
//
|
|
count = ToBox(
|
|
otherState.resistanceZones,
|
|
tmpBoxes //
|
|
);
|
|
|
|
//
|
|
has = IsValidSize(count);
|
|
if (has)
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = tmpBoxes[i];
|
|
|
|
//
|
|
bool isPlacePassed =
|
|
//
|
|
IsBoxInside(
|
|
iBox,
|
|
startBox,
|
|
false,
|
|
false //
|
|
)
|
|
//
|
|
;
|
|
if (!isPlacePassed)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
startZone.resistance = otherState.resistanceZones[i];
|
|
|
|
//
|
|
iBox.Clean();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = startZone.IsValid() &&
|
|
startZone.HasDirection();
|
|
if (result)
|
|
{
|
|
//
|
|
AddRef(
|
|
startZone,
|
|
startZones //
|
|
);
|
|
}
|
|
|
|
//
|
|
Clean(tmpBoxes);
|
|
startBox.Clean();
|
|
startZone.Clean();
|
|
lastStartZone.Clean();
|
|
|
|
//
|
|
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();
|
|
}
|
|
|
|
//
|
|
bool HasConditions(
|
|
double &_pivot,
|
|
double &_point,
|
|
ENUM_X_DIRECTION &conditionsDir,
|
|
XPOIState &state,
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
_pivot = 0;
|
|
_point = 0;
|
|
conditionsDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (forPeriod == NULL)
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(symbol) &&
|
|
IsValid(period) &&
|
|
state.IsValid() &&
|
|
HasWorkingZone() &&
|
|
state.HasChild()
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = false;
|
|
|
|
//
|
|
// Detect Conditions Based On Start Zones ...
|
|
bool hasStartZones = HasStartZones();
|
|
if (hasStartZones)
|
|
{
|
|
//
|
|
int selectedIndex = -1;
|
|
int count = CountStartZones();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
X121SMCXWZZone iStartZone = startZones[i];
|
|
|
|
//
|
|
XBoxZone selectedBox;
|
|
bool hasConditions = false;
|
|
bool isBullish = iStartZone.IsBullish();
|
|
|
|
//
|
|
// Conditions Inside Box ...
|
|
bool isPriceInside = iStartZone.IsPriceInside(
|
|
selectedBox,
|
|
barIndex,
|
|
forPeriod,
|
|
false,
|
|
false //
|
|
);
|
|
if (isPriceInside)
|
|
{
|
|
//
|
|
// hasConditions = iStartZone.HasInsideConditions(
|
|
// state,
|
|
// barIndex,
|
|
// period //
|
|
// );
|
|
|
|
//
|
|
hasConditions = true;
|
|
|
|
//
|
|
if (hasConditions)
|
|
{
|
|
//
|
|
_pivot =
|
|
//
|
|
isBullish
|
|
? selectedBox.lower
|
|
: selectedBox.upper
|
|
//
|
|
;
|
|
|
|
//
|
|
_point =
|
|
//
|
|
isBullish
|
|
? selectedBox.upper
|
|
: selectedBox.lower
|
|
//
|
|
;
|
|
|
|
//
|
|
conditionsDir = selectedBox.dir;
|
|
result = hasConditions;
|
|
iStartZone.Clean();
|
|
break;
|
|
}
|
|
}
|
|
|
|
// //
|
|
// // Order Block Rejection Conditions ...
|
|
// bool hasOBBox = ToBox(
|
|
// selectedBox,
|
|
// iStartZone.ob //
|
|
// );
|
|
// if (hasOBBox &&
|
|
// !hasConditions)
|
|
// {
|
|
// //
|
|
// hasConditions = iStartZone.HasBoxConitions(
|
|
// selectedBox,
|
|
// state,
|
|
// barIndex,
|
|
// forPeriod //
|
|
// );
|
|
|
|
// //
|
|
// if (hasConditions)
|
|
// {
|
|
// //
|
|
// _pivot =
|
|
// //
|
|
// isBullish
|
|
// ? selectedBox.lower
|
|
// : selectedBox.upper
|
|
// //
|
|
// ;
|
|
|
|
// //
|
|
// _point =
|
|
// //
|
|
// isBullish
|
|
// ? selectedBox.upper
|
|
// : selectedBox.lower
|
|
// //
|
|
// ;
|
|
|
|
// //
|
|
// conditionsDir = selectedBox.dir;
|
|
// result = hasConditions;
|
|
// iStartZone.Clean();
|
|
// break;
|
|
// }
|
|
// }
|
|
|
|
// //
|
|
// // Fair Value Gap Rejection Conditions ...
|
|
// bool hasFVGBox = ToBox(
|
|
// selectedBox,
|
|
// iStartZone.fvg //
|
|
// );
|
|
// if (hasFVGBox)
|
|
// {
|
|
// //
|
|
// hasConditions = iStartZone.HasBoxConitions(
|
|
// selectedBox,
|
|
// state,
|
|
// barIndex,
|
|
// forPeriod //
|
|
// );
|
|
|
|
// //
|
|
// if (hasConditions)
|
|
// {
|
|
// //
|
|
// _pivot =
|
|
// //
|
|
// isBullish
|
|
// ? selectedBox.lower
|
|
// : selectedBox.upper
|
|
// //
|
|
// ;
|
|
|
|
// //
|
|
// _point =
|
|
// //
|
|
// isBullish
|
|
// ? selectedBox.upper
|
|
// : selectedBox.lower
|
|
// //
|
|
// ;
|
|
|
|
// //
|
|
// conditionsDir = selectedBox.dir;
|
|
// result = hasConditions;
|
|
// iStartZone.Clean();
|
|
// break;
|
|
// }
|
|
// }
|
|
|
|
//
|
|
iStartZone.Clean();
|
|
}
|
|
|
|
//
|
|
if (result &&
|
|
IsValidIndex(selectedIndex))
|
|
{
|
|
//
|
|
ArrayRemove(
|
|
startZones,
|
|
selectedIndex,
|
|
1 //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect Conditions Based On Working Zones ...
|
|
if (!result)
|
|
{
|
|
//
|
|
// Detect Result Based On WorkingZone ...
|
|
}
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
//
|
|
_point = 0;
|
|
_pivot = 0;
|
|
conditionsDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
bool X121SMCXWZCheckPriceInside(
|
|
XOHCL &zBar,
|
|
XOHCL &cBar,
|
|
double upper,
|
|
double lower //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = zBar.IsValid() &&
|
|
cBar.IsValid() &&
|
|
upper > 0 &&
|
|
lower > 0 &&
|
|
upper > lower &&
|
|
zBar.time > cBar.time;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
zBar.high < upper &&
|
|
cBar.high < upper &&
|
|
//
|
|
zBar.low > lower &&
|
|
cBar.low > lower
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
// |