Files
MQL5Data/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5
T
2025-03-31 07:23:24 +03:30

2784 lines
70 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"
//
// Provided Signals Enumeration ...
enum ENUM_X121SMC_XWZ_PROVIDERS
{
X121SMC_XWZ_PROVIDER_NONE,
X121SMC_XWZ_PROVIDER_XWPVZ,
X121SMC_XWZ_PROVIDER_XFVGMA,
X121SMC_XWZ_PROVIDER_XBREAKED_BOX,
X121SMC_XWZ_PROVIDER_XREJECTED_BOX,
X121SMC_XWZ_PROVIDER_XACTIVATED_BOX,
};
//
// Provided Priority based on Working Zone and
// Quarter Places ...
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,
};
//
// Definitions ...
//
// XWZ Working Zone Model ...
struct X121SMCStrategyXWZWorkingZone
{
//
// Props ...
//
string symbol;
ENUM_TIMEFRAMES period;
//
double quarter1;
double quarter2;
double quarter3;
//
XCSupplyZone *supplyZone;
XCDemandZone *demandZone;
//
XBoxZone support;
XBoxZone resistance;
ENUM_X_DIRECTION trend;
//
XSignalBox waitingBoxes[];
XSignalBox breakedBoxes[];
XSignalBox unavailableBoxes[];
//
CArrayObj mDrawnObjects;
CArrayObj mWorkingZoneObjects;
//
// Constructor ...
X121SMCStrategyXWZWorkingZone()
{
Clean();
}
//
// Properties ...
/**
* Check Working Zone has Supply Zone as Upper Boundary ...
*
* @return ( bool )
*/
bool HasSupplyZone()
{
return supplyZone != NULL &&
supplyZone.IsValid();
}
/**
* Check Working Zone has Demand Zone as Lower Boundary ...
*
* @return ( bool )
*/
bool HasDemandZone()
{
return demandZone != NULL &&
demandZone.IsValid();
}
/**
* Check Working Zone has Waiting Boxes or not ...
*
* @return ( bool )
*/
bool HasWaitingBoxes()
{
return HasChild(waitingBoxes);
}
/**
* Count Working Zone's Waiting Boxes ...
*
* @return ( int )
*/
int CountWaitingBoxes()
{
return ArraySize(waitingBoxes);
}
/**
* Check Working Zone has Breaked Boxes or not ...
*
* @return ( bool )
*/
bool HasBreakedBoxes()
{
return HasChild(breakedBoxes);
}
/**
* Count Working Zone's Breaked Boxes ...
*
* @return ( int )
*/
int CountBreakedBoxes()
{
return ArraySize(breakedBoxes);
}
/**
* Check Working Zone has Unavailable Boxes or not ...
*
* @return ( bool )
*/
bool HasUnavailableBoxes()
{
return HasChild(unavailableBoxes);
}
/**
* Count Working Zone's Unavailable Boxes ...
*
* @return ( int )
*/
int CountUnavailableBoxes()
{
return ArraySize(unavailableBoxes);
}
//
// Tools ...
/**
* Cleanup Model ...
*/
void Clean()
{
//
quarter1 = 0;
quarter2 = 0;
quarter3 = 0;
//
symbol = NULL;
period = NULL;
//
Clean(waitingBoxes);
Clean(breakedBoxes);
Clean(unavailableBoxes);
//
ZeroMemory(supplyZone);
ZeroMemory(demandZone);
//
mDrawnObjects.Clear();
mWorkingZoneObjects.Clear();
}
/**
* Validate Model ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
quarter1 > 0 &&
quarter2 > 0 &&
quarter3 > 0 &&
HasSupplyZone() &&
HasDemandZone() &&
quarter1 > quarter2 &&
quarter2 > quarter3
//
;
//
return result;
}
/**
* Checking a Box Exists in Collections or not ...
*
* @param box: XBoxZone instance reference ...
*
* @return ( bool )
*/
bool IsExists(XSignalBox &box)
{
//
bool result = false;
//
// Check Validation ...
result = box.IsValid() &&
(HasWaitingBoxes() ||
HasBreakedBoxes() ||
HasUnavailableBoxes());
if (!result)
{
return result;
}
//
int idx = -1;
bool has = false;
//
// Check Index in Waiting Boxes ...
has = HasWaitingBoxes();
if (has)
{
//
result = FindIndex(
idx,
box,
waitingBoxes //
);
if (result)
{
return result;
}
}
//
// Check Index in Breaked Boxes ...
has = HasBreakedBoxes();
if (has)
{
//
result = FindIndex(
idx,
box,
breakedBoxes //
);
if (result)
{
return result;
}
}
//
// Check Index in Unavailable Boxes ...
has = HasUnavailableBoxes();
if (has)
{
//
result = FindIndex(
idx,
box,
unavailableBoxes //
);
if (result)
{
return result;
}
}
//
return result;
}
/**
* Initialize Working Zone ...
*
* @param _symbol: String ...
* @param _period: ENUM_TIMEFRAMES member ...
* @param barIndex: int ...
* @param provider: X121SMCStrategySignalProviderData instance reference ...
*
* @return ( bool )
*/
bool Init(
string _symbol,
ENUM_TIMEFRAMES _period,
int barIndex,
X121SMCStrategySignalProviderData &provider //
)
{
//
bool result = false;
//
if (barIndex < 0)
{
barIndex = 0;
}
//
result =
//
IsValid(_symbol) &&
IsValid(_period) &&
//
provider.IsValid()
//
;
if (!result)
{
return result;
}
//
symbol = _symbol;
period = _period;
//
int idx = -1;
int count = 0;
bool has = false;
//
XOHCL zBar;
has = zBar.Init(
symbol,
period,
barIndex //
);
result = has;
if (!result)
{
zBar.Clean();
return result;
}
double ll5 = zBar.FindLowest(5, MODE_LOW);
double hh5 = zBar.FindHighest(5, MODE_HIGH);
zBar.Clean();
//
// Supply Zone ...
has = HasSupplyZone();
if (!has)
{
//
idx = GetHighest(provider
.consolidationState
.supplyZones //
);
has = IsValidIndex(idx);
if (has)
{
//
supplyZone = provider
.consolidationState
.supplyZones[idx];
has = hh5 < supplyZone.Lower();
if (!has)
{
supplyZone = NULL;
}
}
}
//
// Demand Zone ...
has = HasDemandZone();
if (!has)
{
//
idx = GetLowest(provider
.consolidationState
.demandZones //
);
has = IsValidIndex(idx);
if (has)
{
//
demandZone = provider
.consolidationState
.demandZones[idx];
has = ll5 > demandZone.Upper();
if (!has)
{
demandZone = NULL;
}
}
}
//
if (supplyZone != NULL &&
demandZone != NULL &&
supplyZone.IsValid() &&
demandZone.IsValid())
{
//
double upper = supplyZone.Lower();
double lower = demandZone.Upper();
//
double delta = ((upper - lower) / 100) * 25;
//
quarter1 = upper - (1 * delta);
quarter2 = upper - (2 * delta);
quarter3 = upper - (3 * delta);
}
//
result = IsValid();
if (!result)
{
Clean();
}
//
return result;
}
/**
* Detect Signal Boxes ...
*
* @param cycle: ENUM_X_CYCLES member ...
* @param provider: X121SMCStrategySignalProviderData instance reference ...
* @param barIndex: int ...
*
* @return ( bool )
*/
bool DetectWaitingBoxes(
ENUM_X_CYCLES obCycle,
ENUM_X_CYCLES fvgCycle,
X121SMCStrategySignalProviderData &provider,
int barIndex = 0 //
)
{
//
bool result = false;
//
int idx = -1;
int count = 0;
bool has = false;
datetime cTime = TimeCurrent();
//
if (barIndex < 0)
{
barIndex = 0;
}
//
// Select OB Cycle ...
XPOIState obState;
XPOIStateEvents obStateEvents;
X121Conditions obXConditions;
XC121SMCCycleHelper *obHelper;
X121SMCCycleConditions obConditions;
result = provider.SelectCycle(
obCycle,
obState,
obStateEvents,
obXConditions,
obHelper,
obConditions //
);
if (!result)
{
//
obState.Clean();
ZeroMemory(obHelper);
obConditions.Clean();
obStateEvents.Clean();
obXConditions.Clean();
//
return result;
}
//
// Select FVG Cycle ...
XPOIState fvgState;
XPOIStateEvents fvgStateEvents;
X121Conditions fvgXConditions;
XC121SMCCycleHelper *fvgHelper;
X121SMCCycleConditions fvgConditions;
result = provider.SelectCycle(
fvgCycle,
fvgState,
fvgStateEvents,
fvgXConditions,
fvgHelper,
fvgConditions //
);
if (!result)
{
//
obState.Clean();
ZeroMemory(obHelper);
obConditions.Clean();
obStateEvents.Clean();
obXConditions.Clean();
//
fvgState.Clean();
ZeroMemory(fvgHelper);
fvgConditions.Clean();
fvgStateEvents.Clean();
fvgXConditions.Clean();
//
return result;
}
//
// Detect a Sharp Zone Which Contains
// an Order Block and Also an FVG ...
if (obStateEvents.hasNewSharp)
{
//
XBoxZone ob;
XBoxZone fvg;
XBoxZone currSharp;
XBoxZone prevSharp;
XBoxZone sharpConsolidation;
//
// Retrieve Current Sharp ...
XBoxZone tmpBoxes[];
Copy(
obState.sharps,
tmpBoxes //
);
idx = GetYoungest(tmpBoxes);
has = IsValidIndex(idx);
if (has)
{
//
currSharp = tmpBoxes[idx];
bool isBullish = currSharp.IsBullish();
//
ArrayRemove(
tmpBoxes,
idx,
1 //
);
//
while (HasChild(tmpBoxes))
{
//
idx = GetYoungest(tmpBoxes);
has = IsValidIndex(idx);
//
if (!has)
{
break;
}
//
XBoxZone iBox = tmpBoxes[idx];
ArrayRemove(
tmpBoxes,
idx,
1 //
);
//
if (iBox.dir == currSharp.dir)
{
//
prevSharp = iBox;
iBox.Clean();
break;
}
//
iBox.Clean();
}
//
Clean(tmpBoxes);
}
Clean(tmpBoxes);
//
// Preparing Sharp Consolidation Box ...
has = currSharp.IsValid() &&
prevSharp.IsValid() &&
prevSharp.lower < currSharp.upper;
if (has)
{
//
sharpConsolidation.type = "XSHCNZ";
sharpConsolidation.dir = currSharp.dir;
sharpConsolidation.symbol = currSharp.symbol;
sharpConsolidation.period = currSharp.period;
//
sharpConsolidation.from = prevSharp.to;
sharpConsolidation.to = currSharp.from;
//
int toIDX = GetBarIndex(
currSharp.symbol,
currSharp.period,
sharpConsolidation.to //
);
int fromIDX = GetBarIndex(
currSharp.symbol,
currSharp.period,
sharpConsolidation.from //
);
int length = fromIDX - toIDX;
//
XOHCL toBar;
has = toBar.Init(
sharpConsolidation.symbol,
sharpConsolidation.period,
toIDX //
);
//
if (has)
{
//
double upper = toBar.FindHighest(
length,
MODE_HIGH //
);
//
double lower = toBar.FindLowest(
length,
MODE_LOW //
);
//
sharpConsolidation.upper = upper;
sharpConsolidation.lower = lower;
}
//
// Detect Order Block / FVG ...
has = sharpConsolidation.IsValid();
if (has)
{
//
// Check Direction ...
bool isBullish = sharpConsolidation.IsBullish();
//
// Find Inside Order Block ...
Clean(tmpBoxes);
if (isBullish)
{
//
ToBox(
obState.bullishOrderBlocks,
tmpBoxes //
);
}
else
{
//
ToBox(
obState.bearishOrderBlocks,
tmpBoxes //
);
}
//
// Select Order Block ...
has = HasChild(tmpBoxes);
if (has)
{
//
while (HasChild(tmpBoxes))
{
//
idx = GetYoungest(tmpBoxes);
has = IsValidIndex(idx);
if (!has)
{
break;
}
//
XBoxZone iBox = tmpBoxes[idx];
ArrayRemove(
tmpBoxes,
idx,
1 //
);
//
// Validate Selected Box ...
bool isDirPassed = iBox.dir == sharpConsolidation.dir;
bool isFromPassed = iBox.from > sharpConsolidation.from;
bool isInsidePassed = IsBoxInside(
iBox,
sharpConsolidation //
);
bool isValidationPassed = IsBoxValid(
iBox,
barIndex //
);
//
has = isDirPassed &&
isFromPassed &&
isInsidePassed &&
isValidationPassed;
if (has)
{
ob = iBox;
}
//
iBox.Clean();
//
if (ob.IsValid())
{
break;
}
}
}
Clean(tmpBoxes);
//
// Find Inside FVG ...
has = ob.IsValid();
if (has)
{
//
Clean(tmpBoxes);
if (isBullish)
{
//
ToBox(
fvgState.bullishFairValueGaps,
tmpBoxes //
);
}
else
{
//
ToBox(
fvgState.bearishFairValueGaps,
tmpBoxes //
);
}
//
// Select FVG ...
has = HasChild(tmpBoxes);
if (has)
{
//
while (HasChild(tmpBoxes))
{
//
idx = isBullish
? GetLowest(tmpBoxes)
: GetHighest(tmpBoxes);
has = IsValidIndex(idx);
if (!has)
{
break;
}
//
XBoxZone iBox = tmpBoxes[idx];
ArrayRemove(
tmpBoxes,
idx,
1 //
);
//
// Validate Selected Box ...
bool isDirPassed = iBox.dir == ob.dir;
bool isFromPassed = iBox.from > ob.from;
bool isInsidePassed = IsBoxInside(
iBox,
ob //
);
//
has = isDirPassed &&
isFromPassed &&
isInsidePassed;
if (has)
{
fvg = iBox;
}
//
iBox.Clean();
//
if (fvg.IsValid())
{
break;
}
}
}
Clean(tmpBoxes);
}
}
//
// Checking Validation of Boxes ...
has = ob.IsValid() &&
fvg.IsValid() &&
sharpConsolidation.IsValid();
if (has)
{
//
// Update Time ...
ob.to = cTime;
fvg.to = cTime;
sharpConsolidation.to = cTime;
//
XSignalBox iSBox;
//
iSBox.ob = ob;
iSBox.fvg = fvg;
iSBox.sharp = sharpConsolidation;
//
has = iSBox.IsValid();
if (has)
{
//
AddRef(
iSBox,
waitingBoxes //
);
}
//
iSBox.Clean();
}
//
ob.Clean();
fvg.Clean();
toBar.Clean();
currSharp.Clean();
prevSharp.Clean();
sharpConsolidation.Clean();
}
//
Clean(tmpBoxes);
currSharp.Clean();
prevSharp.Clean();
sharpConsolidation.Clean();
}
//
// Preparing Waiting Box based on FVG State ...
if (fvgStateEvents.hasNewSharp)
{
//
// Select Newest Sharp Change ...
XBoxZone sharp;
idx = GetYoungest(fvgState.sharps);
has = IsValidIndex(idx);
if (has)
{
//
XOHCL endBar;
XOHCL startBar;
int totalBars = 0;
int orderBlocksIDX[];
int bullBarsCount = 0;
int bearBarsCount = 0;
int validPercent = 75;
//
sharp = fvgState.sharps[idx];
sharp.type = "XSHPOBX";
bool isSharpBullish = sharp.IsBullish();
//
// Validate End Bar ...
if (sharp.IsValid())
{
//
// Validate End Bar Direction ...
int endBarIDX = GetBarIndex(
sharp.symbol,
sharp.period,
sharp.to //
);
//
has = endBar.Init(
sharp.symbol,
sharp.period,
endBarIDX + 1 //
);
//
if (has)
{
//
has = sharp.dir == endBar.GetDirection();
if (!has)
{
sharp.Clean();
}
}
}
//
// Validate Start Bar ...
if (sharp.IsValid())
{
//
// Validate Start Bar Direction ...
int startBarIDX = GetBarIndex(
sharp.symbol,
sharp.period,
sharp.from //
);
//
has = startBar.Init(
sharp.symbol,
sharp.period,
startBarIDX + 1 //
);
//
if (has)
{
//
has = sharp.dir == Opposit(startBar.GetDirection());
if (!has)
{
sharp.Clean();
}
}
}
//
// Validate OrderBlocks ...
if (sharp.IsValid())
{
//
int end = endBar.Index();
int start = startBar.Index();
for (int i = start; i >= end; i--)
{
//
XOHCL iBar;
has = iBar.Init(
sharp.symbol,
sharp.period,
i //
);
if (!has)
{
//
iBar.Clean();
continue;
}
//
totalBars++;
//
bool isBullish = iBar.IsBullish();
if (isBullish)
{
//
bullBarsCount++;
//
if (!isSharpBullish)
{
//
Add(
i,
orderBlocksIDX //
);
}
}
else
{
//
bearBarsCount++;
//
if (isSharpBullish)
{
//
Add(
i,
orderBlocksIDX //
);
}
}
//
iBar.Clean();
}
//
// Follow Order Blocks ...
has = HasChild(orderBlocksIDX);
if (has)
{
//
int bullBarsPercent = (bullBarsCount * 100) / totalBars;
int bearBarsPercent = (bearBarsCount * 100) / totalBars;
//
has = isSharpBullish
? bullBarsPercent >= validPercent
: bearBarsPercent >= validPercent;
if (has)
{
//
// Prepare Waiting Boxes ...
count = ArraySize(orderBlocksIDX);
for (int i = 0; i < count; i++)
{
//
XOHCL iBar;
has = iBar.Init(
sharp.symbol,
sharp.period,
orderBlocksIDX[i] //
);
if (!has)
{
//
iBar.Clean();
continue;
}
//
XBoxZone iOB;
XBoxZone iFVG;
//
iOB.to = sharp.to;
iOB.type = "XOBX";
iOB.dir = sharp.dir;
iOB.from = iBar.time;
iOB.lower = iBar.low;
iOB.upper = iBar.high;
iOB.period = iBar.period;
iOB.symbol = iBar.symbol;
//
// Select FVG ...
has = iOB.IsValid();
if (has)
{
//
// Select FVG ...
has = HasChild(fvgState.fairValueGaps);
if (has)
{
//
XBoxZone tmpBoxes[];
if (isSharpBullish)
{
//
ToBox(
fvgState.bullishFairValueGaps,
tmpBoxes //
);
}
else
{
//
ToBox(
fvgState.bearishFairValueGaps,
tmpBoxes //
);
}
has = HasChild(tmpBoxes);
if (has)
{
//
while (HasChild(tmpBoxes))
{
//
idx = GetYoungest(tmpBoxes);
has = IsValidIndex(idx);
if (!has)
{
break;
}
//
XBoxZone iBox = tmpBoxes[idx];
ArrayRemove(
tmpBoxes,
idx,
1 //
);
//
// Validate FVG ...
bool isDirPassed = iBox.dir == sharp.dir;
bool isFromPassed = iBox.from >= iOB.from;
bool isPricePassed = IsBoxInsideOr(iBox, iOB);
//
has = isDirPassed &&
isFromPassed &&
isPricePassed;
if (has)
{
//
iFVG = iBox;
iBox.Clean();
break;
}
//
iBox.Clean();
}
}
Clean(tmpBoxes);
}
}
//
has =
sharp.IsValid() &&
iOB.IsValid() &&
iFVG.IsValid();
if (has)
{
//
XSignalBox iSBox;
//
iSBox.ob = iOB;
iSBox.fvg = iFVG;
iSBox.sharp = sharp;
//
AddRef(
iSBox,
waitingBoxes //
);
//
iSBox.Clean();
}
//
iOB.Clean();
iFVG.Clean();
iBar.Clean();
}
}
}
else
{
//
// Follow Non Order Block ...
// First Found FVGs ...
XBoxZone iOB;
XBoxZone iFVG;
XBoxZone tmpBoxes[];
if (isSharpBullish)
{
//
ToBox(
fvgState.bullishFairValueGaps,
tmpBoxes //
);
}
else
{
//
ToBox(
fvgState.bearishFairValueGaps,
tmpBoxes //
);
}
has = HasChild(tmpBoxes);
if (has)
{
//
while (HasChild(tmpBoxes))
{
//
idx = GetYoungest(tmpBoxes);
has = IsValidIndex(idx);
if (!has)
{
break;
}
//
XBoxZone iBox = tmpBoxes[idx];
ArrayRemove(
tmpBoxes,
idx,
1 //
);
//
// Validate FVG ...
bool isDirPassed = iBox.dir == sharp.dir;
bool isFromPassed = iBox.from >= sharp.from;
bool isPricePassed = IsBoxInside(iBox, sharp);
//
has = isDirPassed &&
isFromPassed &&
isPricePassed;
if (has)
{
//
iFVG = iBox;
//
// Now we Have to Create an Order Block ...
//
XOHCL iToBar;
XOHCL iFromBar;
//
int fromIDX = GetBarIndex(
iBox.symbol,
iBox.period,
iBox.from //
);
int toIDX = GetBarIndex(
iBox.symbol,
iBox.period,
iBox.to //
);
has = iToBar.Init(
iBox.symbol,
iBox.period,
toIDX //
);
has =
has &&
iFromBar.Init(
iBox.symbol,
iBox.period,
fromIDX //
);
if (!has)
{
//
iBox.Clean();
iToBar.Clean();
iFromBar.Clean();
//
break;
}
//
iOB.to = iBox.to;
iOB.type = "XOBX";
iOB.dir = iBox.dir;
iOB.from = iBox.from;
iOB.symbol = iBox.symbol;
iOB.period = iBox.period;
iOB.lower = MathMin(iToBar.low, iFromBar.low);
iOB.upper = MathMax(iToBar.high, iFromBar.high);
//
iBox.Clean();
iToBar.Clean();
iFromBar.Clean();
break;
}
//
iBox.Clean();
}
}
Clean(tmpBoxes);
//
has = iOB.IsValid() &&
iFVG.IsValid() &&
sharp.IsValid();
if (has)
{
//
XSignalBox iSBox;
//
iSBox.ob = iOB;
iSBox.fvg = iFVG;
iSBox.sharp = sharp;
//
AddRef(
iSBox,
waitingBoxes //
);
//
iSBox.Clean();
}
//
iOB.Clean();
iFVG.Clean();
}
}
//
endBar.Clean();
startBar.Clean();
Clean(orderBlocksIDX);
}
}
//
count = CountWaitingBoxes();
result = IsValidSize(count);
//
// Cleanup Resources ...
//
obState.Clean();
ZeroMemory(obHelper);
obConditions.Clean();
obStateEvents.Clean();
obXConditions.Clean();
//
fvgState.Clean();
ZeroMemory(fvgHelper);
fvgConditions.Clean();
fvgStateEvents.Clean();
fvgXConditions.Clean();
//
return result;
}
/**
* Validating Waiting Boxes and Detect Breaked Boxes ...
*
* @param barIndex: int ...
*
* @return ( int )
*/
int ValidateWaitingBoxes(
int barIndex = 0 //
)
{
//
int result = 0;
//
bool has = false;
//
if (barIndex < 0)
{
barIndex = 0;
}
//
if (barIndex == 0)
{
barIndex = 1;
}
//
has = HasWaitingBoxes();
if (!has)
{
return result;
}
//
int removeIDX[];
result = CountWaitingBoxes();
for (int i = 0; i < result; i++)
{
//
XOHCL iBar;
XSignalBox iBox = waitingBoxes[i];
bool isInite = iBar.Init(
iBox.ob.symbol,
iBox.ob.period,
iBox.ob.from //
);
//
has = isInite &&
(
//
IsBoxBreaked(
iBox.ob,
iBar.Index() - 1,
barIndex,
period //
)
//
);
if (has)
{
//
Add(
i,
removeIDX //
);
//
AddRef(
iBox,
breakedBoxes //
);
}
//
// iBox.Clean();
iBar.Clean();
}
//
has = HasChild(removeIDX);
if (has)
{
//
CleanupArray(
removeIDX,
waitingBoxes //
);
}
Clean(removeIDX);
//
result = CountWaitingBoxes();
//
return result;
}
/**
* Detect Trend Based On Boxes ...
*
* @param dir: ENUM_X_DIRECTION ember ...
*
* @return ( bool )
*/
bool DetectTreand(
ENUM_X_CYCLES cycle,
ENUM_X_DIRECTION &dir,
X121SMCStrategySignalProviderData &provider,
int barIndex = 0 //
)
{
//
bool result = false;
//
support.Clean();
resistance.Clean();
dir = X_DIRECTION_NONE;
trend = X_DIRECTION_NONE;
//
if (barIndex < 0)
{
barIndex = 0;
}
//
result = IsValid(cycle);
if (!result)
{
return result;
}
//
// Select Cycle ...
XPOIState cState;
XPOIStateEvents cStateEvents;
X121Conditions cXConditions;
XC121SMCCycleHelper *cHelper;
X121SMCCycleConditions cConditions;
result = provider.SelectCycle(
cycle,
cState,
cStateEvents,
cXConditions,
cHelper,
cConditions //
);
if (!result)
{
//
cState.Clean();
ZeroMemory(cHelper);
cConditions.Clean();
cStateEvents.Clean();
cXConditions.Clean();
//
return result;
}
//
// Detect Trend ...
//
int idx = -1;
bool has = false;
//
XBoxZone tmp[];
XBoxZone tmpBoxes[];
//
// Select Supports ...
ToBox(
cState.supportZones,
tmp //
);
Copy(
tmp,
tmpBoxes,
false //
);
Clean(tmp);
//
// Select Resistances ...
ToBox(
cState.resistanceZones,
tmp //
);
Copy(
tmp,
tmpBoxes,
false //
);
Clean(tmp);
//
result = HasChild(tmpBoxes);
if (!result)
{
//
Clean(tmpBoxes);
//
cState.Clean();
ZeroMemory(cHelper);
cConditions.Clean();
cStateEvents.Clean();
cXConditions.Clean();
//
return result;
}
//
// Select Youngest Valid Zone ...
while (HasChild(tmpBoxes) ||
!(support.IsValid() &&
resistance.IsValid()))
{
//
// Check Yongest Zone ...
idx = GetYoungest(tmpBoxes);
has = IsValidIndex(idx);
if (!has)
{
break;
}
//
// Remove Extracted Box ...
XBoxZone iBox = tmpBoxes[idx];
ArrayRemove(
tmpBoxes,
idx,
1 //
);
//
// Check Validation of Box ...
has = IsBoxValid(
iBox,
barIndex,
period //
);
if (!has)
{
//
iBox.Clean();
continue;
}
//
// Assign Support or Resistance ...
bool isBullish = iBox.IsBullish();
if (isBullish &&
!support.IsValid())
{
support = iBox;
}
else if (!isBullish &&
!resistance.IsValid())
{
resistance = iBox;
}
//
// Validate Support and Resistance ...
has =
support.IsValid() &&
resistance.IsValid();
if (!has)
{
//
iBox.Clean();
continue;
}
//
iBox.Clean();
}
//
// Checking Result ...
bool isBullish =
support.from > resistance.from;
bool isBearish =
support.from < resistance.from;
result = isBullish ||
isBearish;
if (result)
{
//
dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
trend = dir;
//
support.to = TimeCurrent();
resistance.to = TimeCurrent();
}
//
// Cleanup Resources ...
//
Clean(tmp);
cState.Clean();
Clean(tmpBoxes);
ZeroMemory(cHelper);
cConditions.Clean();
cStateEvents.Clean();
cXConditions.Clean();
//
return result;
}
/**
* Update all Collections Members To Time ...
*
* @param value: datetime, Specified To Time ...
*/
void UpdateTo(datetime value = NULL)
{
//
value = NormalizeTime(value);
//
int count = 0;
bool has = false;
//
has = HasSupplyZone();
if (has)
{
supplyZone.To(value);
}
//
has = HasDemandZone();
if (has)
{
demandZone.To(value);
}
//
has = HasWaitingBoxes();
if (has)
{
//
count = CountWaitingBoxes();
for (int i = 0; i < count; i++)
{
waitingBoxes[i].UpdateTo(value);
}
}
//
}
/**
* Check Working Zone is Destroyed or not ...
*
* @param barIndex: int, bar index ...
* @param forPeriod: ENUM_TIMEFRAMES member ...
*
* @return ( bool )
*/
bool IsDestroyed(
int barIndex = 0,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
if (barIndex < 0)
{
barIndex = 0;
}
//
if (!IsValid(forPeriod))
{
forPeriod = period;
}
//
result = IsValid();
if (!result)
{
return result;
}
//
XOHCL bar;
result = bar.Init(
symbol,
period,
barIndex //
);
if (!result)
{
//
bar.Clean();
return result;
}
//
XOHCL cBar;
result = bar.GetPreviousBar(cBar);
if (!result)
{
//
bar.Clean();
cBar.Clean();
//
return result;
}
//
bool isSupplyZoneBreaked =
//
bar.low > supplyZone.Upper() &&
cBar.low > supplyZone.Upper()
//
;
//
bool isDemandZoneBreaked =
//
bar.high < demandZone.Lower() &&
cBar.high < demandZone.Lower()
//
;
//
bar.Clean();
cBar.Clean();
//
result = isSupplyZoneBreaked ||
isDemandZoneBreaked;
//
return result;
}
/**
* Detect Signal Box Conditions ...
*
* @param box: XBoxZone instance reference, Signalled Box ...
* @param dir: ENUM_X_DIRECTION member, Specified Signal Direction ...
* @param signalProvider: ENUM_X121SMC_XWZ_PROVIDERS member, Specified Signal Type ...
* @param provider: X121SMCStrategySignalProviderData instance reference ...
* @param barIndex: int ...
*
* @return ( bool )
*/
bool DetectSignalConditions(
XSignalBox &box,
ENUM_X_DIRECTION &dir,
ENUM_X121SMC_XWZ_PROVIDERS &signalProvider,
X121SMCStrategySignalProviderData &provider,
int barIndex = 0 //
)
{
//
bool result = false;
//
// Normalize Bars ...
//
box.Clean();
dir = X_DIRECTION_NONE;
signalProvider = X121SMC_XWZ_PROVIDER_NONE;
//
if (barIndex < 0)
{
barIndex = 0;
}
//
// TODO: Ignor Working Zone Validation ...
// result = IsValid();
// if (!result)
// {
// return result;
// }
//
int idx = -1;
int count = 0;
bool has = false;
//
int zIDX = barIndex;
int cIDX = zIDX + 1;
int pIDX = cIDX + 1;
//
bool isBullish = false;
bool isBearish = false;
//
// Senario 1:
// ---------------------------------------------
// Rejected Box ...
// ---------------------------------------------
bool useSenario1 = false;
bool isSenario1Happend = false;
bool isSenario1Bullish = false;
bool isSenario1Bearish = false;
if (useSenario1)
{
//
isSenario1Happend = false;
//
isSenario1Bullish =
isSenario1Happend &&
IsBullish(dir);
//
isSenario1Bearish =
isSenario1Happend &&
IsBearish(dir);
//
if (isSenario1Happend)
{
signalProvider = X121SMC_XWZ_PROVIDER_XREJECTED_BOX;
}
}
//
// Senario 2:
// ---------------------------------------------------
// Activated Box ...
// ---------------------------------------------------
bool useSenario2 = false;
bool isSenario2Happend = false;
bool isSenario2Bullish = false;
bool isSenario2Bearish = false;
if (!isSenario1Happend &&
useSenario2)
{
//
isSenario2Happend = false;
//
isSenario2Bullish =
isSenario2Happend &&
IsBullish(dir);
//
isSenario2Bearish =
isSenario2Happend &&
IsBearish(dir);
//
if (isSenario2Happend)
{
signalProvider = X121SMC_XWZ_PROVIDER_XACTIVATED_BOX;
}
}
//
// Senario 3:
// ---------------------------------------------------
// Breaked Box ...
// ---------------------------------------------------
bool useSenario3 = false;
bool isSenario3Happend = false;
bool isSenario3Bullish = false;
bool isSenario3Bearish = false;
if (!isSenario1Happend &&
!isSenario2Happend &&
useSenario3)
{
//
isSenario3Happend = false;
//
isSenario3Bullish =
isSenario3Happend &&
IsBullish(dir);
//
isSenario3Bearish =
isSenario3Happend &&
IsBearish(dir);
//
if (isSenario3Happend)
{
signalProvider = X121SMC_XWZ_PROVIDER_XACTIVATED_BOX;
}
}
//
// Senario 4:
// -----------------------------------------------
// Detect Signal Box Based On FVG Conditions ...
// -----------------------------------------------
bool useSenario4 = false;
bool isSenario4Happend = false;
bool isSenario4Bullish = false;
bool isSenario4Bearish = false;
if (!isSenario1Happend &&
!isSenario2Happend &&
!isSenario3Happend &&
useSenario4)
{
//
isSenario4Happend = false;
//
isSenario4Bullish =
isSenario4Happend &&
IsBullish(dir);
//
isSenario4Bearish =
isSenario4Happend &&
IsBearish(dir);
//
if (isSenario4Happend)
{
signalProvider = X121SMC_XWZ_PROVIDER_XFVGMA;
}
}
//
// Senario 5:
// ---------------------------------------------
// XWPVZ ...
// ---------------------------------------------
bool useSenario5 = true;
bool isSenario5Happend = false;
bool isSenario5Bullish = false;
bool isSenario5Bearish = false;
if (!isSenario1Happend &&
!isSenario2Happend &&
!isSenario3Happend &&
!isSenario4Happend &&
useSenario5)
{
//
isSenario5Happend = false;
//
isSenario5Bullish =
isSenario5Happend &&
IsBullish(dir);
//
isSenario5Bearish =
isSenario5Happend &&
IsBearish(dir);
//
if (isSenario5Happend)
{
signalProvider = X121SMC_XWZ_PROVIDER_XWPVZ;
}
}
//
// Senario 6:
// ---------------------------------------------
// ---------------------------------------------
bool useSenario6 = false;
bool isSenario6Happend = false;
bool isSenario6Bullish = false;
bool isSenario6Bearish = false;
if (!isSenario1Happend &&
!isSenario2Happend &&
!isSenario3Happend &&
!isSenario4Happend &&
!isSenario5Happend &&
useSenario6)
{
}
//
// Summarize All Senario(s) Conditions ...
//
isBullish =
//
isSenario1Bullish ||
isSenario2Bullish ||
isSenario3Bullish ||
isSenario4Bullish ||
isSenario5Bullish ||
isSenario6Bullish
//
;
//
isBearish =
//
isSenario1Bearish ||
isSenario2Bearish ||
isSenario3Bearish ||
isSenario4Bearish ||
isSenario5Bearish ||
isSenario6Bearish
//
;
//
// Check All Conditions ...
result =
box.IsValid() &&
HasDirection(dir) &&
(isBullish ||
isBearish);
//
if (!result)
{
box.Clean();
}
//
return result;
}
/**
* Detect a Signal Priority forDynamic Risk Reward ratio ...
*
* @param priority: ENUM_X121SMC_XWZ_PRIORITY member, holds Specified position Priority ...
* @param forDir: ENUM_X_DIRECTION member, Specified Position Direction for Priority ...
* @param barIndex: int ...
* @param forPeriod: ENUM_TIMEFRAMES member ...
*
* @return ( bool )
*/
bool DetectPriority(
ENUM_X121SMC_XWZ_PRIORITY &priority,
ENUM_X_DIRECTION forDir,
int barIndex = 0,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
bool result = false;
//
priority = X121SMC_XWZ_PRIORITY_NONE;
//
if (barIndex < 0)
{
barIndex = 0;
}
//
if (!IsValid(forPeriod))
{
forPeriod = period;
}
//
result = IsValid() &&
HasDirection(forDir);
if (!result)
{
return result;
}
//
bool isBullish = IsBullish(forDir);
//
XOHCL bar;
result = bar.Init(
symbol,
forPeriod,
barIndex //
);
if (!result)
{
//
bar.Clean();
return result;
}
//
if (bar.high < supplyZone.Upper() &&
bar.low > supplyZone.Lower())
{
//
priority =
isBullish
? X121SMC_XWZ_PRIORITY_NONE
: X121SMC_XWZ_PRIORITY_STRONG_HIGH;
}
else if (bar.high < supplyZone.Lower() &&
bar.low > quarter1)
{
//
priority =
isBullish
? X121SMC_XWZ_PRIORITY_WEAK
: X121SMC_XWZ_PRIORITY_HIGH;
}
else if (bar.high < quarter1 &&
bar.low > quarter2)
{
//
priority =
isBullish
? X121SMC_XWZ_PRIORITY_LOW
: X121SMC_XWZ_PRIORITY_REGULAR;
}
else if (bar.high < quarter2 &&
bar.low > quarter3)
{
//
priority =
isBullish
? X121SMC_XWZ_PRIORITY_REGULAR
: X121SMC_XWZ_PRIORITY_LOW;
}
else if (bar.high < quarter3 &&
bar.low > demandZone.Upper())
{
//
priority =
isBullish
? X121SMC_XWZ_PRIORITY_HIGH
: X121SMC_XWZ_PRIORITY_WEAK;
}
else if (bar.high < demandZone.Upper() &&
bar.low > demandZone.Lower())
{
//
priority =
isBullish
? X121SMC_XWZ_PRIORITY_STRONG_HIGH
: X121SMC_XWZ_PRIORITY_NONE;
}
//
result = priority != X121SMC_XWZ_PRIORITY_NONE &&
priority != X121SMC_XWZ_PRIORITY_WEAK;
//
bar.Clean();
//
return result;
}
/**
* Draw Working Zne and all of
* it's Collections and Conditions ...
*
* @param drawSupplyZone: boolean ...
* @param drawDemandZone: boolean ...
* @param drawWaitingBoxes: boolean ...
*/
void Draw(
XCPOIDrawer *drawer,
bool drawSupplyZone = false,
bool drawDemandZone = false,
bool drawWaitingBoxes = false,
bool drawTrend = false //
)
{
//
if (drawer == NULL)
{
return;
}
//
int count = 0;
bool has = false;
bool isCreated = false;
//
ulong chartID = drawer.ChartIdentification();
int subWindow = drawer.SubWindowIdentification();
color bullishColor = drawer.BarBullishColor();
color bearishColor = drawer.BarBearishColor();
//
// Supply Zone ...
if (drawSupplyZone)
{
//
has = HasSupplyZone();
if (has)
{
//
XCSupplyZoneObject *iObj;
isCreated = drawer.CreateSupplyZone(
supplyZone,
iObj //
);
//
if (isCreated)
{
mWorkingZoneObjects.Add(iObj);
}
}
}
//
// Demand Zone ...
if (drawDemandZone)
{
//
has = HasDemandZone();
if (has)
{
//
XCDemandZoneObject *iObj;
isCreated = drawer.CreateDemandZone(
demandZone,
iObj //
);
//
if (isCreated)
{
mWorkingZoneObjects.Add(iObj);
}
}
}
//
//
//
//
// Quarters ...
has = IsValid();
if (has)
{
//
double zoneUpper = supplyZone.Upper();
double upper = supplyZone.Lower();
//
double lower = demandZone.Upper();
double zoneLower = demandZone.Lower();
//
string prefix = "X121WZone_" + symbol + "_" + ToString(period);
//
// Zone Upper ...
CChartObjectHLine *zoneUpperLine;
zoneUpperLine = new CChartObjectHLine();
isCreated = zoneUpperLine.Create(
chartID,
prefix + "_ZoneTop",
subWindow,
zoneUpper //
);
if (isCreated)
{
//
zoneUpperLine.Color(clrRed);
//
mWorkingZoneObjects.Add(zoneUpperLine);
}
//
// Zone Lower ...
CChartObjectHLine *zoneLowerLine;
zoneLowerLine = new CChartObjectHLine();
isCreated = zoneLowerLine.Create(
chartID,
prefix + "_ZoneDown",
subWindow,
zoneLower //
);
if (isCreated)
{
//
zoneLowerLine.Color(clrRed);
//
mWorkingZoneObjects.Add(zoneLowerLine);
}
//
// Upper ...
CChartObjectHLine *upperLine;
upperLine = new CChartObjectHLine();
isCreated = upperLine.Create(
chartID,
prefix + "_Upper",
subWindow,
upper //
);
if (isCreated)
{
//
upperLine.Color(clrLime);
//
mWorkingZoneObjects.Add(upperLine);
}
//
// Lower ...
CChartObjectHLine *lowerLine;
lowerLine = new CChartObjectHLine();
isCreated = lowerLine.Create(
chartID,
prefix + "_Lower",
subWindow,
lower //
);
if (isCreated)
{
//
lowerLine.Color(clrLime);
//
mWorkingZoneObjects.Add(lowerLine);
}
//
// Quarters ...
//
// Quarter 1 ...
CChartObjectHLine *q1Line;
q1Line = new CChartObjectHLine();
isCreated = q1Line.Create(
chartID,
prefix + "_Q1",
subWindow,
quarter1 //
);
if (isCreated)
{
//
q1Line.Color(clrYellow);
//
mWorkingZoneObjects.Add(q1Line);
}
//
// Quarter 2 ...
CChartObjectHLine *q2Line;
q2Line = new CChartObjectHLine();
isCreated = q2Line.Create(
chartID,
prefix + "_Q2",
subWindow,
quarter2 //
);
if (isCreated)
{
//
q2Line.Color(clrYellow);
//
mWorkingZoneObjects.Add(q2Line);
}
//
// Quarter 3 ...
CChartObjectHLine *q3Line;
q3Line = new CChartObjectHLine();
isCreated = q3Line.Create(
chartID,
prefix + "_Q3",
subWindow,
quarter3 //
);
if (isCreated)
{
//
q3Line.Color(clrYellow);
//
mWorkingZoneObjects.Add(q3Line);
}
}
//
// Waiting Zones ...
if (drawWaitingBoxes)
{
//
has = HasWaitingBoxes();
if (has)
{
//
count = CountWaitingBoxes();
for (int i = 0; i < count; i++)
{
//
XCBaseObject *objects[];
has = drawer.DrawSignalBox(
waitingBoxes[i],
objects //
);
if (has)
{
//
int objectsCount = ArraySize(objects);
for (int i = 0; i < objectsCount; i++)
{
mWorkingZoneObjects.Add(objects[i]);
}
}
Clean(objects);
}
}
}
//
// Draw Trend if Exists ...
if (drawTrend)
{
//
// Check Trend Exists ...
has =
support.IsValid() &&
HasDirection(trend) &&
resistance.IsValid();
if (has)
{
//
// Draw Support ...
XCBoxObject *supportObject;
has = drawer.DrawBox(
support,
supportObject //
);
if (has)
{
mWorkingZoneObjects.Add(supportObject);
}
//
// Draw Resistance ...
XCBoxObject *resistanceObject;
has = drawer.DrawBox(
resistance,
resistanceObject //
);
if (has)
{
mWorkingZoneObjects.Add(resistanceObject);
}
}
}
//
}
//
};
//
// XWZ Signal Conditions ...
struct X121SMCStrategyXWZSignalConditions
{
//
// Props ...
//
string symbol;
ENUM_TIMEFRAMES period;
//
double sl;
double reward;
double amountPercent;
ENUM_X_DIRECTION dir;
ENUM_X_POSITION_TYPES type;
//
// Setup Props ...
//
datetime setupTime;
datetime triggerTime;
//
double pivot;
double point;
double sls[];
double targets[];
//
XBoxZone signalBox;
//
ENUM_X121SMC_XWZ_PRIORITY priority;
ENUM_X121SMC_XWZ_PROVIDERS provider;
//
// Constructor ...
X121SMCStrategyXWZSignalConditions()
{
Clean();
}
//
// Tools ...
/**
* Cleaning Up ...
*/
void Clean()
{
//
sl = 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;
//
reward = 0;
amountPercent = 0;
//
Clean(sls);
Clean(targets);
signalBox.Clean();
//
provider = X121SMC_XWZ_PROVIDER_NONE;
}
//
//
//
//
void UpdateTo(datetime value = NULL)
{
//
value = NormalizeTime(value);
//
int count = 0;
bool has = false;
}
//
};
//
// Extension Functions ...
//