2324 lines
52 KiB
Plaintext
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;
|
|
}
|
|
|
|
//
|