Files
MQL5Data/X121SMCEA/Signals/x-121.smc.xobs.signal.lib.mq5
T
2025-02-04 19:31:24 +03:30

2324 lines
52 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 X121 SMC Signal Class
// -------------------------------------------------
// Name: XOBS
// 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"
//
struct XOBTest
{
//
// Props ...
//
string symbol;
ENUM_TIMEFRAMES period;
//
XCOrderBlock *ob;
XCFVG *fvgs[];
//
datetime fvgActedAt;
datetime rewardedAt;
//
double reward;
//
// Constructor ...
XOBTest()
{
Clean();
}
//
// Tools ...
//
void Clean()
{
//
ob = NULL;
symbol = NULL;
period = NULL;
rewardedAt = NULL;
fvgActedAt = NULL;
//
reward = 0;
//
Clean(fvgs);
}
//
bool HasOB()
{
return ob != NULL &&
ob.IsValid();
}
//
int CountFVGs()
{
return ArraySize(fvgs);
}
//
bool HasFVGs()
{
return IsValidSize(CountFVGs());
}
};
//
// Definitions ...
struct X121SMCStrategyXOBSSignalConditions
{
//
// Props ...
//
string symbol;
ENUM_TIMEFRAMES period;
//
double sl;
double target;
ENUM_X_DIRECTION dir;
ENUM_X_POSITION_TYPES type;
//
// Setup Props ...
//
datetime setupTime;
datetime triggerTime;
//
double pivot;
double point;
//
// Extwnsion ...
XOBTest obTests[];
//
// Constructor ...
X121SMCStrategyXOBSSignalConditions()
{
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;
//
Clean(obTests);
}
//
};
//
// Signaller Data Sources ...
X121SMCStrategyXOBSSignalConditions mXOBSConditions;
X121SMCStrategyXOBSSignalConditions mXOBSConditionsCollection[];
//
// Extension Functions ...
//
// Detect Setup Conditions ...
bool DetectX121SMCXOBSSignalSetup(
string _symbol,
ENUM_TIMEFRAMES _period,
//
X121SMCStrategyXOBSSignalConditions &conditions,
//
XC121SMCCycleHelper *triggerCycleHelper,
XC121SMCCycleHelper *decisionCycleHelper,
XC121SMCCycleHelper *analyseCycleHelper,
XC121SMCCycleHelper *verificationCycleHelper,
XC121SMCCycleHelper *consolidationCycleHelper,
XC121SMCCycleHelper *visionCycleHelper,
//
int resetAfterUnActedZoneInMinutes = 120
//
)
{
//
bool result = false;
//
bool isBullish = false;
bool isBearish = false;
//
int zIndex = 0;
int cIndex = zIndex + 1;
int pIndex = cIndex + 1;
int ppIndex = pIndex + 1;
//
int loopback = 10;
//
string symbol = _symbol;
ENUM_TIMEFRAMES period = _period;
//
conditions.symbol = symbol;
conditions.period = period;
//
XC121SMCCycleHelper *barCycle = triggerCycleHelper;
//
XOHCL zBar;
result = barCycle.GetBar(
zBar,
zIndex //
);
if (!result)
{
return result;
}
//
XOHCL cBar;
result = barCycle.GetBar(
cBar,
cIndex //
);
if (!result)
{
return result;
}
//
XOHCL pBar;
result = barCycle.GetBar(
pBar,
pIndex //
);
if (!result)
{
return result;
}
//
double ask = GetAsk(symbol);
double bid = GetBid(symbol);
datetime cTime = TimeCurrent();
double points = GetPoints(symbol);
//
int swingLoopback = 7;
double ll = cBar.FindLowest(swingLoopback, MODE_LOW);
double hh = cBar.FindHighest(swingLoopback, MODE_HIGH);
double ll50 = cBar.FindLowest(50, MODE_LOW);
double hh50 = cBar.FindHighest(50, MODE_HIGH);
double llDown = cBar.FindLowesttDown(swingLoopback);
double hhUp = cBar.FindHighestUp(swingLoopback);
//
// Cycles Conditions ...
//
// Trigger ...
ENUM_XPOI_EVENTS triggerPoiEvents[];
ENUM_X_CYCLE_EVENTS triggerCycleEvents[];
X121SMCCycleConditions triggerConditions;
result = triggerCycleHelper.GetConditions(
triggerCycleEvents,
triggerPoiEvents,
triggerConditions,
zIndex,
loopback //
);
if (!result)
{
return result;
}
//
// Decision ...
ENUM_XPOI_EVENTS decisionPoiEvents[];
ENUM_X_CYCLE_EVENTS decisionCycleEvents[];
X121SMCCycleConditions decisionConditions;
result = decisionCycleHelper.GetConditions(
decisionCycleEvents,
decisionPoiEvents,
decisionConditions,
zIndex,
loopback //
);
if (!result)
{
return result;
}
//
// Analyse ...
ENUM_XPOI_EVENTS analysePoiEvents[];
ENUM_X_CYCLE_EVENTS analyseCycleEvents[];
X121SMCCycleConditions analyseConditions;
result = analyseCycleHelper.GetConditions(
analyseCycleEvents,
analysePoiEvents,
analyseConditions,
zIndex,
loopback //
);
if (!result)
{
return result;
}
//
// Verification ...
ENUM_XPOI_EVENTS verificationPoiEvents[];
ENUM_X_CYCLE_EVENTS verificationCycleEvents[];
X121SMCCycleConditions verificationConditions;
result = verificationCycleHelper.GetConditions(
verificationCycleEvents,
verificationPoiEvents,
verificationConditions,
zIndex,
loopback //
);
if (!result)
{
return result;
}
//
// Consolidation ...
ENUM_XPOI_EVENTS consolidationPoiEvents[];
ENUM_X_CYCLE_EVENTS consolidationCycleEvents[];
X121SMCCycleConditions consolidationConditions;
result = consolidationCycleHelper.GetConditions(
consolidationCycleEvents,
consolidationPoiEvents,
consolidationConditions,
zIndex,
loopback //
);
if (!result)
{
return result;
}
//
// Vision ...
ENUM_XPOI_EVENTS visionPoiEvents[];
ENUM_X_CYCLE_EVENTS visionCycleEvents[];
X121SMCCycleConditions visionConditions;
result = visionCycleHelper.GetConditions(
visionCycleEvents,
visionPoiEvents,
visionConditions,
zIndex,
loopback //
);
if (!result)
{
return result;
}
//
// Cycles POI States ...
XPOIState triggerState = triggerConditions.state;
XPOIState decisionState = decisionConditions.state;
XPOIState analyseState = analyseConditions.state;
XPOIState verificationState = verificationConditions.state;
XPOIState consolidationState = consolidationConditions.state;
XPOIState visionState = visionConditions.state;
//
// Cycle X121Conditions ...
X121Conditions triggerXConditions = triggerConditions.x121Conditions;
X121Conditions decisionXConditions = decisionConditions.x121Conditions;
X121Conditions analyseXConditions = analyseConditions.x121Conditions;
X121Conditions verificationXConditions = verificationConditions.x121Conditions;
X121Conditions consolidationXConditions = consolidationConditions.x121Conditions;
X121Conditions visionXConditions = visionConditions.x121Conditions;
//
// Setup Conditions ...
//
// Detect Bar State ...
//
// PinBar ...
ENUM_X_DIRECTION cBarPinDir;
bool isCBarPin = decisionCycleHelper
.mBarAnalyser
.IsPinBar(
cBar,
cBarPinDir,
1 //
);
bool isCBarBullishPin =
isCBarPin &&
IsBullish(cBarPinDir);
bool isCBarBearishPin =
isCBarPin &&
IsBearish(cBarPinDir);
//
// Engulf ...
ENUM_X_DIRECTION cBarEngulfDir;
bool isCBarEngulfed = decisionCycleHelper
.mBarAnalyser
.IsEngulfBar(
cBar,
cBarEngulfDir,
0 // Extended ...
);
bool isCBarBullishEngulfed =
isCBarEngulfed &&
IsBullish(cBarEngulfDir);
bool isCBarBearishEngulfed =
isCBarEngulfed &&
IsBearish(cBarEngulfDir);
//
// Momentum ...
ENUM_X_DIRECTION cBarMomentumDir;
bool isCBarMomentum = decisionCycleHelper
.mBarAnalyser
.IsMomentumBar(
cBar,
cBarMomentumDir,
0 // Extended ...
);
bool isCBarBullishMomentum =
isCBarMomentum &&
IsBullish(cBarMomentumDir);
bool isCBarBearishMomentum =
isCBarMomentum &&
IsBearish(cBarMomentumDir);
//
// Reject ...
ENUM_X_DIRECTION cBarRejectDir;
bool isCBarRejected = decisionCycleHelper
.mBarAnalyser
.IsRejectionBar(
cBar,
cBarRejectDir,
0 // Extended ...
);
bool isCBarBullishRejected =
isCBarRejected &&
IsBullish(cBarRejectDir);
bool isCBarBearishRejected =
isCBarRejected &&
IsBearish(cBarRejectDir);
//
// Pull Back ...
ENUM_X_DIRECTION cBarPullbackDir;
bool isCBarPullbacked =
decisionCycleHelper
.mBarAnalyser
.HasPullBack(
cBarPullbackDir,
cBar //
);
bool isCBarBullishPullbacked =
isCBarPullbacked &&
IsBullish(cBarPullbackDir);
bool isCBarBearishPullbacked =
isCBarPullbacked &&
IsBearish(cBarPullbackDir);
//
// HH/LL Break ...
//
bool isCBarBreaksUpHH = IsBarBreak(
hh,
X_DIRECTION_BULLISH,
cBar //
);
//
bool isCBarBreaksDownLL = IsBarBreak(
hh,
X_DIRECTION_BEARISH,
cBar //
);
//
// Bars Pattern and Power and Pressures ...
//
bool hasCBarBullishPattern =
decisionCycleHelper
.mBarAnalyser
.HasBullishPattern(
cBar,
2 //
);
//
bool hasCBarBearishPattern =
decisionCycleHelper
.mBarAnalyser
.HasBearishPattern(
cBar,
2 //
);
//
bool isCBarHasBullishPower =
decisionCycleHelper
.mBarAnalyser
.HasBullishPower(
cBar,
2 //
);
//
bool isCBarHasBearishPower =
decisionCycleHelper
.mBarAnalyser
.HasBearishPower(
cBar,
2 //
);
//
bool isCBarHasBullishPressure =
decisionCycleHelper
.mBarAnalyser
.HasBullishPressure(
cBar,
2 //
);
//
bool isCBarHasBearishPressure =
decisionCycleHelper
.mBarAnalyser
.HasBearishPressure(
cBar,
2 //
);
//
// Bar Checking Summary ...
//
// Bullish ...
bool isCBarBullishFormed =
//
(
//
hasCBarBullishPattern &&
isCBarHasBullishPower &&
isCBarHasBullishPressure
//
)
//
||
//
(
//
isCBarBullishPin ||
isCBarBreaksUpHH ||
isCBarBullishEngulfed ||
isCBarBullishMomentum ||
isCBarBullishRejected
//
)
//
;
//
// Bearish ...
bool isCBarBearishFormed =
//
(
//
hasCBarBearishPattern &&
isCBarHasBearishPower &&
isCBarHasBearishPressure
//
)
//
||
//
(
//
isCBarBearishPin ||
isCBarBreaksDownLL ||
isCBarBearishEngulfed ||
isCBarBearishMomentum ||
isCBarBearishRejected
//
)
//
;
//
// Detect Order Flow ...
//
// Test Market For Order Flow ...
int obTestsCount = ArraySize(conditions.obTests);
bool isOBTested = obTestsCount == 2;
if (!isOBTested)
{
//
bool hasTest = ReTestMarket(
conditions.obTests,
consolidationState,
analyseState,
decisionState,
visionCycleHelper.mPOIDrawer //
);
}
//
// TODO:
return false;
//
double upper = 0;
double lower = 0;
//
//
//
//
// Summarize Conditions ...
//
bool isCondition1Bullish =
//
false
//
;
//
bool isCondition1Bearish =
//
false
//
;
//
bool hasCondition1 = isCondition1Bullish ||
isCondition1Bearish;
if (hasCondition1)
{
//
ENUM_X_DIRECTION pzDir =
isCondition1Bullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
double point = GetEntry(
conditions.symbol,
pzDir //
);
//
double longPivot = lower; // triggerXConditions.valesBuffer[1];
double shortPivot = upper; // triggerXConditions.peaksBuffer[1];
//
// Manipulate Conditions Point ...
//
conditions.point =
isCondition1Bullish
? shortPivot
: longPivot;
//
// Manipulate Conditions Pivot ...
//
conditions.pivot =
isCondition1Bullish
? longPivot
: shortPivot;
}
//
//
//
//
isBullish =
//
isCondition1Bullish
//
;
//
isBearish =
//
isCondition1Bearish
//
;
//
result = isBullish ||
isBearish;
if (!result)
{
//
// Detect PriceOB Lifetime Bars ...
//
// Cleanup Arrays ...
Clean(triggerPoiEvents);
Clean(triggerCycleEvents);
Clean(decisionPoiEvents);
Clean(decisionCycleEvents);
Clean(analysePoiEvents);
Clean(analyseCycleEvents);
Clean(verificationPoiEvents);
Clean(verificationCycleEvents);
Clean(consolidationPoiEvents);
Clean(consolidationCycleEvents);
Clean(visionPoiEvents);
Clean(visionCycleEvents);
//
return result;
}
//
conditions.setupTime = cTime;
conditions.dir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Cleanup Arrays ...
Clean(triggerPoiEvents);
Clean(triggerCycleEvents);
Clean(decisionPoiEvents);
Clean(decisionCycleEvents);
Clean(analysePoiEvents);
Clean(analyseCycleEvents);
Clean(verificationPoiEvents);
Clean(verificationCycleEvents);
Clean(consolidationPoiEvents);
Clean(consolidationCycleEvents);
Clean(visionPoiEvents);
Clean(visionCycleEvents);
//
return result;
}
//
// Detect Trigger Conditions ...
bool DetectX121SMCXOBSSignalTrigger(
//
X121SMCStrategyXOBSSignalConditions &conditions,
//
string _symbol,
ENUM_TIMEFRAMES _period,
//
XC121SMCCycleHelper *triggerCycleHelper,
XC121SMCCycleHelper *decisionCycleHelper,
XC121SMCCycleHelper *analyseCycleHelper,
XC121SMCCycleHelper *verificationCycleHelper,
XC121SMCCycleHelper *consolidationCycleHelper,
XC121SMCCycleHelper *visionCycleHelper,
//
int maxAllowedSetupAge = 60 //
//
)
{
//
bool result = false;
//
result = conditions.IsSetuped();
if (!result)
{
return result;
}
//
datetime setupTime = conditions.setupTime;
ENUM_X_DIRECTION setupDir = conditions.dir;
//
bool isBullish = IsBullish(setupDir);
bool isBearish = IsBearish(setupDir);
//
int zIndex = 0;
int cIndex = zIndex + 1;
int pIndex = cIndex + 1;
int ppIndex = pIndex + 1;
//
int loopback = 10;
//
string symbol = _symbol;
ENUM_TIMEFRAMES period = _period;
//
XOHCL zBar;
result = decisionCycleHelper.GetBar(
zBar,
zIndex //
);
if (!result)
{
return result;
}
//
XOHCL cBar;
result = decisionCycleHelper.GetBar(
cBar,
cIndex //
);
if (!result)
{
return result;
}
//
XOHCL pBar;
result = decisionCycleHelper.GetBar(
pBar,
pIndex //
);
if (!result)
{
return result;
}
//
double ask = GetAsk(symbol);
double bid = GetBid(symbol);
datetime cTime = TimeCurrent();
double points = GetPoints(symbol);
//
int swingLoopback = 9;
double ll = cBar.FindLowest(swingLoopback, MODE_LOW);
double hh = cBar.FindHighest(swingLoopback, MODE_HIGH);
double llDown = cBar.FindLowesttDown(swingLoopback);
double hhUp = cBar.FindHighestUp(swingLoopback);
//
// Cycles Conditions ...
//
// Decision ...
ENUM_XPOI_EVENTS decisionPoiEvents[];
ENUM_X_CYCLE_EVENTS decisionCycleEvents[];
X121SMCCycleConditions decisionConditions;
result = decisionCycleHelper.GetConditions(
decisionCycleEvents,
decisionPoiEvents,
decisionConditions,
zIndex,
loopback //
);
if (!result)
{
return result;
}
//
// Cycles POI States ...
XPOIState decisionState = decisionConditions.state;
//
// Cycle X121Conditions ...
X121Conditions decisionXConditions = decisionConditions.x121Conditions;
//
// Trigger Conditions ...
//
// Slopes ...
//
bool isRsiSlopeBullish = decisionXConditions.isRsiSlopeBullish;
bool isStrSlopeBullish = decisionXConditions.isStrSlopeBullish;
bool isAtrUpperSlopeBullish = decisionXConditions.isAtrUpperSlopeBullish;
bool isAtrLowerSlopeBullish = decisionXConditions.isAtrLowerSlopeBullish;
bool isVwapFastSlopeBullish = decisionXConditions.isVwapFastSlopeBullish;
bool isVwapMidSlopeBullish = decisionXConditions.isVwapMidSlopeBullish;
bool isVwapSlowSlopeBullish = decisionXConditions.isVwapSlowSlopeBullish;
//
bool isRsiSlopeBearish = decisionXConditions.isRsiSlopeBearish;
bool isStrSlopeBearish = decisionXConditions.isStrSlopeBearish;
bool isAtrUpperSlopeBearish = decisionXConditions.isAtrUpperSlopeBearish;
bool isAtrLowerSlopeBearish = decisionXConditions.isAtrLowerSlopeBearish;
bool isVwapFastSlopeBearish = decisionXConditions.isVwapFastSlopeBearish;
bool isVwapMidSlopeBearish = decisionXConditions.isVwapMidSlopeBearish;
bool isVwapSlowSlopeBearish = decisionXConditions.isVwapSlowSlopeBearish;
//
bool isSlopesBullish =
isRsiSlopeBullish &&
isStrSlopeBullish &&
isAtrUpperSlopeBullish &&
isAtrLowerSlopeBullish &&
isVwapFastSlopeBullish &&
isVwapMidSlopeBullish &&
isVwapSlowSlopeBullish;
//
bool isSlopesBearish =
isRsiSlopeBearish &&
isStrSlopeBearish &&
isAtrUpperSlopeBearish &&
isAtrLowerSlopeBearish &&
isVwapFastSlopeBearish &&
isVwapMidSlopeBearish &&
isVwapSlowSlopeBearish;
//
double point = conditions.point;
bool isPointBreaked = IsBarBreak(
point,
setupDir,
cBar //
);
//
// Summary ...
//
isBullish =
//
isBullish &&
isPointBreaked &&
isSlopesBullish
//
;
//
isBearish =
//
isBearish &&
isPointBreaked &&
isSlopesBearish
//
;
//
result = isBullish ||
isBearish;
if (!result)
{
//
// Cleanup Setup Conditions ...
int setupAge = conditions.GetSetupAge();
if (IsValidSize(setupAge) &&
IsValidSize(maxAllowedSetupAge) &&
setupAge >= maxAllowedSetupAge)
{
conditions.Clean();
}
//
// Cleanup Arrays ...
Clean(decisionPoiEvents);
Clean(decisionCycleEvents);
//
return result;
}
//
// Detect Nearest Pivot Point ...
//
double entry = GetEntry(
conditions.symbol,
setupDir //
);
//
double sls[];
Add(
conditions.pivot,
sls //
);
//
double iAtr = decisionConditions.x121Conditions.atrBuffer[1];
iAtr *= 1.5;
//
double slsMin = GetMin(sls);
double slsMax = GetMax(sls);
//
double sl = isBullish
? slsMin - iAtr
: slsMax + iAtr;
double risk = MathAbs(entry - sl);
//
// Filling Conditions Props ...
conditions.sl = sl;
// conditions.target = target;
conditions.triggerTime = cTime;
conditions.type = isBullish
? X_POSITION_TYPE_LONG
: X_POSITION_TYPE_SHORT;
//
// Cleanup Arrays ...
Clean(decisionPoiEvents);
Clean(decisionCycleEvents);
//
return result;
}
//
// Detect Guards ...
bool DetectX121SMCXOBSGuards(
X121SMCGuard &guards[],
const XPosition &positions[],
XC121SMCCycleHelper *triggerCycleHelper,
XC121SMCCycleHelper *decisionCycleHelper,
XC121SMCCycleHelper *analyseCycleHelper,
XC121SMCCycleHelper *verificationCycleHelper,
XC121SMCCycleHelper *consolidationCycleHelper,
XC121SMCCycleHelper *visionCycleHelper //
)
{
//
bool result = false;
//
string provider = ToString(X_121_SMC_PROVIDER_X);
//
result = DetectX121SMCGuards(
provider,
guards,
positions,
triggerCycleHelper,
decisionCycleHelper,
analyseCycleHelper,
verificationCycleHelper,
consolidationCycleHelper,
visionCycleHelper,
//
true, // CloseOnTPNear Guard ...
true, // CloseLongsOnBearishTrend Guard ...
true, // CloseShortsOnBullishTrend Guard ...
true, // CloseAllWeekend Guard ...
true, // PartialCloseOnTrendChange Guard ...
true, // TrailStop Guard ...
true, // TrailTarget Guard ...
true // Hedge Guard ...
//
);
//
return result;
}
//
// Add Conditions to Conditions Collection ...
int AddX121SMCXOBSConditionsIfNotExists(
X121SMCStrategyXOBSSignalConditions &item,
X121SMCStrategyXOBSSignalConditions &items[],
int maxAllowed = 10 //
)
{
//
int result = 0;
//
bool isSetuped = IsValid(item.setupTime) &&
HasDirection(item.dir);
if (!isSetuped)
{
return result;
}
//
int count = ArraySize(items);
if (IsValidSize(count))
{
//
// Copy Original Items ...
X121SMCStrategyXOBSSignalConditions tmpItems[];
Copy(
items,
tmpItems //
);
//
// Prese Item Data ...
bool isBullish = IsBullish(item.dir);
//
for (int i = 0; i < count; i++)
{
//
X121SMCStrategyXOBSSignalConditions iItem = tmpItems[i];
//
bool canRemove = item.dir == iItem.dir &&
item.pivot == iItem.pivot;
if (canRemove)
{
//
ArrayRemove(
items,
i,
1 //
);
}
}
//
Clean(tmpItems);
}
//
AddRef(
item,
items //
);
//
// Remove Olds ...
CleanupArray(
items,
maxAllowed //
);
//
result = ArraySize(items);
//
return result;
}
//
//
//
/**
* Retest Market ...
*
* @param test: XOBTest instance Reference, Represet Result Test ...
* @param tests: XOBTest instance Reference Collection, Represet Founded Tests till now ...
* @param htfState: XPOIState instance Reference ...
* @param mtfState: XPOIState instance Reference ...
* @param ttfState: XPOIState instance Reference ...
*
* @return ( bool )
*/
bool ReTestMarket(
XOBTest &tests[],
XPOIState &htfState,
XPOIState &mtfState,
XPOIState &ttfState, //
//
XCPOIDrawer *drawer
//
)
{
//
bool result = false;
//
Clean(tests);
//
datetime cTime = TimeCurrent();
//
// Detect Order Blocks ...
// HTF ...
//
// Bullish OBs ...
XCOrderBlock *bullOBs[];
bool hasYoungestBullOB = false;
XOHCL youngestBullOBStartedBar;
bool isYoungestBullOBStarted = false;
ENUM_X_DIRECTION youngestBullOBStartedDir;
XCOrderBlock *youngestBullOB = NULL;
int bullOBsCount = ExtractUnActivatedOBs(
htfState.bullishOrderBlocks,
bullOBs //
);
//
bool isBullOBsPassed = bullOBsCount >= 1;
if (isBullOBsPassed)
{
//
XBoxZone boxes[];
int boxesCount = ToBox(
bullOBs,
boxes //
);
int youngestBoxIDX = GetYoungest(boxes);
hasYoungestBullOB = IsValidIndex(youngestBoxIDX);
if (hasYoungestBullOB)
{
//
youngestBullOB = bullOBs[youngestBoxIDX];
//
isYoungestBullOBStarted = youngestBullOB.IsStarted(
X_DIRECTION_BULLISH,
youngestBullOBStartedBar,
youngestBullOBStartedDir //
);
}
}
//
// Bearish OBs ...
XCOrderBlock *bearOBs[];
bool hasYoungestBearOB = false;
XOHCL youngestBearOBStartedBar;
bool isYoungestBearOBStarted = false;
ENUM_X_DIRECTION youngestBearOBStartedDir;
XCOrderBlock *youngestBearOB = NULL;
int bearOBsCount = ExtractUnActivatedOBs(
htfState.bearishOrderBlocks,
bearOBs //
);
//
bool isBearOBsPassed = bearOBsCount >= 1;
if (isBearOBsPassed)
{
//
XBoxZone boxes[];
int boxesCount = ToBox(
bearOBs,
boxes //
);
int youngestBoxIDX = GetYoungest(boxes);
hasYoungestBearOB = IsValidIndex(youngestBoxIDX);
if (hasYoungestBearOB)
{
//
youngestBearOB = bearOBs[youngestBoxIDX];
//
isYoungestBearOBStarted = youngestBearOB.IsStarted(
X_DIRECTION_BEARISH,
youngestBearOBStartedBar,
youngestBearOBStartedDir //
);
}
}
//
bool hasYoungestOB = hasYoungestBullOB ||
hasYoungestBearOB;
result = hasYoungestOB;
if (!result)
{
return result;
}
//
// Since Youngest Order Blocks is UnActivated ...
// here we found Order Flow ...
// Order Blocks in consequences of Youngest OB which they
// Breaked ...
//
// Bullish OB ...
int breakedBullOBsCount = 0;
XCOrderBlock *breakedBullOBs[];
bool hasBreakedBullOBs = false;
if (hasYoungestBullOB)
{
//
bool hasOBs = htfState.HasBullishOrderBlocks();
int count = htfState.CountBullishOrderBlocks();
if (hasOBs)
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iOB = htfState.bullishOrderBlocks[i];
ENUM_X_DIRECTION forDir =
iOB.IsBullish()
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Check iOB isn't Same as Youngest OB ...
bool isSameAsYoungest = IsSame(
youngestBullOB,
iOB //
);
if (isSameAsYoungest)
{
continue;
}
//
// Bullish Order Blocks must appears Below
// Youngest One ...
bool isBelow = IsBelow(
iOB,
youngestBullOB //
);
if (!isBelow)
{
continue;
}
//
XOHCL iBreakerBar;
ENUM_X_DIRECTION iBreakerDir;
bool isIBreaked = iOB.IsBreaked(
forDir,
iBreakerBar,
iBreakerDir //
);
if (!isIBreaked)
{
continue;
}
//
// Bullish Order Block Must Valid ...
// Means Price Must be On Top of it after its breake out ...
//
bool isValid = false;
int fromIndex = iBreakerBar.Index() - 1;
for (int i = fromIndex; i >= 0; i--)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
iOB.GetSymbol(),
iOB.GetPeriod(),
i //
);
if (!isInited)
{
continue;
}
//
isValid = iBar.low > iOB.Upper();
if (!isValid)
{
break;
}
}
if (!isValid)
{
continue;
}
//
// Set OB's To Time to Breaker Bar's Time ...
iOB.To(iBreakerBar.time);
//
// Check Order Block Not Exists ...
int iOBIDX = -1;
bool isIOBExists = FindIndex(
iOBIDX,
iOB,
breakedBullOBs //
);
if (isIOBExists)
{
continue;
}
//
Add(
iOB,
breakedBullOBs //
);
//
}
}
//
breakedBullOBsCount = ArraySize(breakedBullOBs);
hasBreakedBullOBs = IsValidSize(breakedBullOBsCount);
}
//
// Bearish OB ...
int breakedBearOBsCount = 0;
XCOrderBlock *breakedBearOBs[];
bool hasBreakedBearOBs = false;
if (hasYoungestBearOB)
{
//
bool hasOBs = htfState.HasBearishOrderBlocks();
int count = htfState.CountBearishOrderBlocks();
if (hasOBs)
{
//
for (int i = 0; i < count; i++)
{
//
XCOrderBlock *iOB = htfState.bearishOrderBlocks[i];
ENUM_X_DIRECTION forDir =
iOB.IsBullish()
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Check iOB isn't Same as Youngest OB ...
bool isSameAsYoungest = IsSame(
youngestBearOB,
iOB //
);
if (isSameAsYoungest)
{
continue;
}
//
// Bearish Order Blocks must appears Above
// Youngest One ...
bool isAbove = IsAbove(
iOB,
youngestBearOB //
);
if (!isAbove)
{
continue;
}
//
XOHCL iBreakerBar;
ENUM_X_DIRECTION iBreakerDir;
bool isIBreaked = iOB.IsBreaked(
forDir,
iBreakerBar,
iBreakerDir //
);
if (!isIBreaked)
{
continue;
}
//
// Bearish Order Block Must Valid ...
// Means Price Must be On Bottom of it after its breake out ...
//
bool isValid = false;
int fromIndex = iBreakerBar.Index() - 1;
for (int i = fromIndex; i >= 0; i--)
{
//
XOHCL iBar;
bool isInited = iBar.Init(
iOB.GetSymbol(),
iOB.GetPeriod(),
i //
);
if (!isInited)
{
continue;
}
//
isValid = iBar.high < iOB.Lower();
if (!isValid)
{
break;
}
}
if (!isValid)
{
continue;
}
//
// Set OB's To Time to Breaker Bar's Time ...
iOB.To(iBreakerBar.time);
//
// Check Order Block Not Exists ...
int iOBIDX = -1;
bool isIOBExists = FindIndex(
iOBIDX,
iOB,
breakedBearOBs //
);
if (isIOBExists)
{
continue;
}
//
Add(
iOB,
breakedBearOBs //
);
//
}
}
//
breakedBearOBsCount = ArraySize(breakedBearOBs);
hasBreakedBearOBs = IsValidSize(breakedBearOBsCount);
}
//
bool hasBreakedOBs = hasBreakedBullOBs ||
hasBreakedBearOBs;
result = hasBreakedOBs;
if (!result)
{
return result;
}
//
// Update Youngest OB To time ...
//
if (hasYoungestBullOB)
{
youngestBullOB.To(cTime);
}
//
if (hasYoungestBearOB)
{
youngestBearOB.To(cTime);
}
//
// Now we Have to Validate Breaked Order Blocks Count in additions to
// Youngest OB directions ...
//
bool hasBullishOrderFlow =
//
hasYoungestBullOB &&
isYoungestBullOBStarted &&
//
breakedBullOBsCount >= 2
//
;
//
bool hasBearishOrderFlow =
//
hasYoungestBearOB &&
isYoungestBearOBStarted &&
//
breakedBearOBsCount >= 2
//
;
//
ENUM_X_DIRECTION orderFlowDir = X_DIRECTION_NONE;
bool hasOrderFlow = hasBullishOrderFlow ||
hasBearishOrderFlow;
if (hasOrderFlow)
{
//
orderFlowDir =
hasBullishOrderFlow
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
}
result = hasOrderFlow;
if (!result)
{
return result;
}
//
// here we have try to detect Fair Value Gaps in Related to OrderFlow ...
if (hasBullishOrderFlow)
{
//
for (int i = 0; i < breakedBullOBsCount; i++)
{
//
XCOrderBlock *iOB = breakedBullOBs[i];
//
XOHCL iOBBreakerBar;
ENUM_X_DIRECTION iOBBreakerDir;
bool isIOBBreaked = iOB.IsBreaked(
X_DIRECTION_BULLISH,
iOBBreakerBar,
iOBBreakerDir //
);
if (!isIOBBreaked)
{
continue;
}
//
int fvgsCount = mtfState.CountBullishFairValueGaps();
bool hasFVGs = mtfState.HasBullishFairValueGaps();
if (!hasFVGs)
{
break;
}
//
XCFVG *iOBFVGs[];
datetime fvgActedAt = NULL;
for (int j = 0; j < fvgsCount; j++)
{
//
XCFVG *jFVG = mtfState.bullishFairValueGaps[j];
//
bool isFromPassed = jFVG.From() >= iOB.From();
if (!isFromPassed)
{
continue;
}
//
bool isAbovePassed = IsAboveDiff(
jFVG,
iOB,
true // Ignore Inside FVG ...
);
if (!isAbovePassed)
{
continue;
}
//
// Validate FVG Based on Conditions ...
// for Bullish Order Blocks FVGs must Rejected as Liquidity ...
// in ttf ...
//
XOHCL rejectedBar;
ENUM_X_DIRECTION rejectedDir;
bool isRejected = jFVG.IsRejected(
X_DIRECTION_BULLISH,
rejectedBar,
rejectedDir,
NULL, // From ...
true, // Force Sweeped ...
ttfState.period // For Period ...
);
//
XOHCL breakedBar;
ENUM_X_DIRECTION breakedDir;
bool isBreaked = jFVG.IsBreaked(
X_DIRECTION_BULLISH,
breakedBar,
breakedDir //
);
//
bool isFVGActed =
isRejected ||
isBreaked;
if (!isFVGActed)
{
continue;
}
//
datetime iFvgActedAt =
isBreaked &&
!isRejected
? breakedBar.time
: !isBreaked &&
isRejected
? rejectedBar.time
: isBreaked &&
isRejected
? (breakedBar.time < rejectedBar.time)
? breakedBar.time
: rejectedBar.time
: NULL;
if (!IsValid(iFvgActedAt))
{
continue;
}
//
if (!IsValid(fvgActedAt)) {
fvgActedAt = iFvgActedAt;
}
//
XCFVG *lastFVG = NULL;
int fvgsCount = ArraySize(iOBFVGs);
bool hasLastFVG = IsValidSize(fvgsCount);
if (hasLastFVG)
{
lastFVG = iOBFVGs[fvgsCount - 1];
}
bool isLastPassed =
!hasLastFVG
? true
: IsAbove(
jFVG,
lastFVG,
true // Ignore Inside ...
);
if (!isLastPassed)
{
continue;
}
//
jFVG.To(iOB.To());
jFVG.To(iFvgActedAt);
//
Add(
jFVG,
iOBFVGs //
);
}
//
// Check Order Block Has FVG or Not ...
int iOBFVGsCount = ArraySize(iOBFVGs);
bool iOBHasFVG = IsValidSize(iOBFVGsCount);
if (iOBHasFVG)
{
//
XOBTest iTest;
//
iTest.ob = iOB;
iTest.symbol = iOB.GetSymbol();
iTest.period = iOB.GetPeriod();
//
iTest.fvgActedAt = fvgActedAt;
//
Copy(
iOBFVGs,
iTest.fvgs //
);
//
AddRef(
iTest,
tests //
);
//
iTest.Clean();
}
}
}
else if (hasBearishOrderFlow)
{
//
for (int i = 0; i < breakedBearOBsCount; i++)
{
//
XCOrderBlock *iOB = breakedBearOBs[i];
//
XOHCL iOBBreakerBar;
ENUM_X_DIRECTION iOBBreakerDir;
bool isIOBBreaked = iOB.IsBreaked(
X_DIRECTION_BULLISH,
iOBBreakerBar,
iOBBreakerDir //
);
if (!isIOBBreaked)
{
continue;
}
//
int fvgsCount = mtfState.CountBearishFairValueGaps();
bool hasFVGs = mtfState.HasBearishFairValueGaps();
if (!hasFVGs)
{
break;
}
//
XCFVG *iOBFVGs[];
datetime fvgActedAt = NULL;
for (int j = 0; j < fvgsCount; j++)
{
//
XCFVG *jFVG = mtfState.bearishFairValueGaps[j];
//
bool isFromPassed = jFVG.From() >= iOB.From();
if (!isFromPassed)
{
continue;
}
//
bool isBelowPassed = IsBelowDiff(
jFVG,
iOB,
true // Ignore Inside FVG ...
);
if (!isBelowPassed)
{
continue;
}
//
// Validate FVG Based on Conditions ...
// for Bearish Order Blocks FVGs must Rejected as Liquidity ...
// in ttf ...
//
XOHCL rejectedBar;
ENUM_X_DIRECTION rejectedDir;
bool isRejected = jFVG.IsRejected(
X_DIRECTION_BEARISH,
rejectedBar,
rejectedDir,
NULL, // From ...
true, // Force Sweeped ...
ttfState.period // For Period ...
);
//
XOHCL breakedBar;
ENUM_X_DIRECTION breakedDir;
bool isBreaked = jFVG.IsBreaked(
X_DIRECTION_BEARISH,
breakedBar,
breakedDir //
);
//
bool isFVGActed =
isRejected ||
isBreaked;
if (!isFVGActed)
{
continue;
}
//
datetime iFvgActedAt =
isBreaked &&
!isRejected
? breakedBar.time
: !isBreaked &&
isRejected
? rejectedBar.time
: isBreaked &&
isRejected
? (breakedBar.time < rejectedBar.time)
? breakedBar.time
: rejectedBar.time
: NULL;
if (!IsValid(iFvgActedAt))
{
continue;
}
//
if (!IsValid(fvgActedAt)) {
fvgActedAt = iFvgActedAt;
}
//
XCFVG *lastFVG = NULL;
int fvgsCount = ArraySize(iOBFVGs);
bool hasLastFVG = IsValidSize(fvgsCount);
if (hasLastFVG)
{
lastFVG = iOBFVGs[fvgsCount - 1];
}
bool isLastPassed =
!hasLastFVG
? true
: IsBelow(
jFVG,
lastFVG,
true // Ignore Inside ...
);
if (!isLastPassed)
{
continue;
}
//
jFVG.To(iOB.To());
jFVG.To(iFvgActedAt);
//
Add(
jFVG,
iOBFVGs //
);
}
//
// Check Order Block Has FVG or Not ...
int iOBFVGsCount = ArraySize(iOBFVGs);
bool iOBHasFVG = IsValidSize(iOBFVGsCount);
if (iOBHasFVG)
{
//
XOBTest iTest;
//
iTest.ob = iOB;
iTest.symbol = iOB.GetSymbol();
iTest.period = iOB.GetPeriod();
//
iTest.fvgActedAt = fvgActedAt;
//
Copy(
iOBFVGs,
iTest.fvgs //
);
//
AddRef(
iTest,
tests //
);
//
iTest.Clean();
}
}
}
//
// Now we Have to Works On Tests Collection ...
//
int testsCount = ArraySize(tests);
bool hasTests = testsCount >= 2;
result = hasTests;
if (!result)
{
return result;
}
//
// DRAW ...
//
//
XCBaseObject *drawnObjects[];
//
if (hasYoungestBullOB)
{
//
XCBullishOrderBlockObject *iObj;
bool isCreated = drawer
.CreateBullishOrderBlock(
youngestBullOB,
iObj //
);
//
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
//
if (hasYoungestBearOB)
{
//
XCBearishOrderBlockObject *iObj;
bool isCreated = drawer
.CreateBearishOrderBlock(
youngestBearOB,
iObj //
);
//
if (isCreated)
{
//
Add(
(XCBaseObject *)iObj,
drawnObjects //
);
}
}
// //
// // Draw Breaked Bullish OrderBlocks ...
// if (hasBreakedBullOBs)
// {
// //
// for (int i = 0; i < breakedBullOBsCount; i++)
// {
// //
// XCOrderBlock *iOB = breakedBullOBs[i];
// // iOB.To(cTime);
// //
// XCBullishOrderBlockObject *iObj;
// bool isCreated = drawer
// .CreateBullishOrderBlock(
// iOB,
// iObj //
// );
// //
// if (isCreated)
// {
// //
// Add(
// (XCBaseObject *)iObj,
// drawnObjects //
// );
// }
// }
// }
// //
// // Draw Breaked Bearish OrderBlocks ...
// if (hasBreakedBearOBs)
// {
// //
// for (int i = 0; i < breakedBearOBsCount; i++)
// {
// //
// XCOrderBlock *iOB = breakedBearOBs[i];
// // iOB.To(cTime);
// //
// XCBearishOrderBlockObject *iObj;
// bool isCreated = drawer
// .CreateBearishOrderBlock(
// iOB,
// iObj //
// );
// //
// if (isCreated)
// {
// //
// Add(
// (XCBaseObject *)iObj,
// drawnObjects //
// );
// }
// }
// }
//
// Draw Tests ...
if (hasTests)
{
//
for (int i = 0; i < testsCount; i++)
{
//
XOBTest iTest = tests[i];
//
bool hasOB = iTest.HasOB();
if (hasOB)
{
//
bool isBullish = iTest.ob.IsBullish();
//
XCBaseObject *obObj;
bool isCreated = drawer
.CreateOrderBlock(
iTest.ob,
obObj //
);
if (isCreated)
{
//
Add(
obObj,
drawnObjects //
);
}
}
//
bool hasFVGs = iTest.HasFVGs();
int fvgsCount = iTest.CountFVGs();
for (int j = 0; j < fvgsCount; j++)
{
//
XCFVG *jFVG = iTest.fvgs[j];
// jFVG.To(iTest.ob.To());
//
XCBaseObject *fvgObj;
bool isCreated = drawer
.CreateFairValueGap(
jFVG,
fvgObj //
);
if (isCreated)
{
//
Add(
fvgObj,
drawnObjects //
);
}
}
}
}
//
// END DRAW ...
//
//
Print("OBs Passed ...");
//
return result;
}
/**
* Extract UnActivated Order Blocks ...
*
* @return ( int )
*/
int ExtractUnActivatedOBs(
XCOrderBlock *&source[],
XCOrderBlock *&obs[] //
)
{
//
int result = 0;
//
Clean(obs);
//
int count = ArraySize(source);
bool hasOB = IsValidSize(count);
if (!hasOB)
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
bool isBullish = source[i].IsBullish();
ENUM_X_DIRECTION forDir =
isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
//
//
//
XOHCL activatedBar;
ENUM_X_DIRECTION activatedDir;
bool isActivated = source[i].IsActivated(
forDir,
activatedBar,
activatedDir //
);
if (!isActivated)
{
//
Add(
source[i],
obs //
);
}
}
//
result = ArraySize(obs);
//
return result;
}
//