5474 lines
130 KiB
Plaintext
5474 lines
130 KiB
Plaintext
#include "../Signals/x-121.smc.xhkpv.signal.lib.mq5"
|
|
#include "../Signals/x-121.smc.xiobpv.signal.lib.mq5"
|
|
#include "../Signals/x-121.smc.xobpv.signal.lib.mq5"
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
bool useXHKPVSignal;
|
|
bool useXOBPVSignal;
|
|
bool useXIOBPVSignal;
|
|
|
|
Clean(mXHKPVConditionsCollection);
|
|
Clean(mXOBPVConditionsCollection);
|
|
Clean(mXIOBPVConditionsCollection);
|
|
|
|
bool hasXHKPVSignal = false;
|
|
bool hasXOBPVSignal = false;
|
|
bool hasXIOBPVSignal = false;
|
|
|
|
useXHKPVSignal = false;
|
|
useXOBPVSignal = false;
|
|
useXIOBPVSignal = false;
|
|
|
|
//
|
|
// XHKPV Signal ...
|
|
if (useXHKPVSignal && !hasSignal)
|
|
{
|
|
//
|
|
hasXHKPVSignal = DetectXHKPVSignal(conditions);
|
|
hasSignal = hasXHKPVSignal;
|
|
}
|
|
|
|
//
|
|
// XOBPV Signal ...
|
|
if (useXOBPVSignal && !hasSignal)
|
|
{
|
|
//
|
|
hasXOBPVSignal = DetectXOBPVSignal(conditions);
|
|
hasSignal = hasXOBPVSignal;
|
|
}
|
|
|
|
//
|
|
// XIOBPV Signal ...
|
|
if (useXIOBPVSignal && !hasSignal)
|
|
{
|
|
//
|
|
hasXIOBPVSignal = DetectXIOBPVSignal(conditions);
|
|
hasSignal = hasXIOBPVSignal;
|
|
}
|
|
|
|
//
|
|
// XHKPV Guard Detection ...
|
|
if (useXHKPVSignal)
|
|
{
|
|
//
|
|
bool hasGuard = DetectX121SMCXHKPVGuards(
|
|
guards,
|
|
positions,
|
|
mTriggerCycleHelper,
|
|
mDecisionCycleHelper,
|
|
mAnalyseCycleHelper,
|
|
mVerificationCycleHelper,
|
|
mConsolidationCycleHelper,
|
|
mVisionCycleHelper //
|
|
);
|
|
}
|
|
|
|
//
|
|
// XOBPV Guard Detection ...
|
|
if (useXOBPVSignal)
|
|
{
|
|
//
|
|
bool hasGuard = DetectX121SMCXOBPVGuards(
|
|
guards,
|
|
positions,
|
|
mTriggerCycleHelper,
|
|
mDecisionCycleHelper,
|
|
mAnalyseCycleHelper,
|
|
mVerificationCycleHelper,
|
|
mConsolidationCycleHelper,
|
|
mVisionCycleHelper //
|
|
);
|
|
}
|
|
|
|
//
|
|
// XIOBPV Guard Detection ...
|
|
if (useXIOBPVSignal)
|
|
{
|
|
//
|
|
bool hasGuard = DetectX121SMCXIOBPVGuards(
|
|
guards,
|
|
positions,
|
|
mTriggerCycleHelper,
|
|
mDecisionCycleHelper,
|
|
mAnalyseCycleHelper,
|
|
mVerificationCycleHelper,
|
|
mConsolidationCycleHelper,
|
|
mVisionCycleHelper //
|
|
);
|
|
}
|
|
|
|
//
|
|
// XHKPV Signal ...
|
|
bool DetectXHKPVSignal(
|
|
X121SMCStrategyConditions &conditions //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
int zIndex = 0;
|
|
int cIndex = zIndex + 1;
|
|
int pIndex = cIndex + 1;
|
|
int ppIndex = pIndex + 1;
|
|
|
|
//
|
|
string symbol = GetSymbol();
|
|
ENUM_TIMEFRAMES period = GetPeriod();
|
|
|
|
//
|
|
XOHCL zBar;
|
|
result = zBar.Init(
|
|
symbol,
|
|
period,
|
|
zIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL cBar;
|
|
result = cBar.Init(
|
|
symbol,
|
|
period,
|
|
cIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL pBar;
|
|
result = pBar.Init(
|
|
symbol,
|
|
period,
|
|
pIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double cLL = cBar.FindLowest(7, MODE_LOW);
|
|
double cHH = cBar.FindHighest(7, MODE_HIGH);
|
|
|
|
//
|
|
datetime cTime = TimeCurrent();
|
|
|
|
//
|
|
ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_XHKPV;
|
|
string providerStr = ToString(provider);
|
|
|
|
//
|
|
// Detect Setup Conditions ...
|
|
datetime setupTime = mXHKPVConditions.setupTime;
|
|
bool isSetuped = mXHKPVConditions.IsSetuped();
|
|
ENUM_X_DIRECTION setupDir = mXHKPVConditions.dir;
|
|
if (!isSetuped)
|
|
{
|
|
//
|
|
// Detect Signal Setup ...
|
|
isSetuped = DetectX121SMCXHKPVSignalSetup(
|
|
symbol,
|
|
period,
|
|
mXHKPVConditions,
|
|
mTriggerCycleHelper,
|
|
mDecisionCycleHelper,
|
|
mAnalyseCycleHelper,
|
|
mVerificationCycleHelper,
|
|
mConsolidationCycleHelper,
|
|
mVisionCycleHelper //
|
|
);
|
|
|
|
//
|
|
setupDir = mXHKPVConditions.dir;
|
|
setupTime = mXHKPVConditions.setupTime;
|
|
|
|
//
|
|
if (isSetuped)
|
|
{
|
|
//
|
|
int items = AddX121SMCXHKPVConditionsIfNotExists(
|
|
mXHKPVConditions,
|
|
mXHKPVConditionsCollection //
|
|
);
|
|
|
|
//
|
|
mXHKPVConditions.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
int conditionsCount = ArraySize(mXHKPVConditionsCollection);
|
|
result = IsValidSize(conditionsCount);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Looking For Conditions ...
|
|
int selectedIndex = 0;
|
|
X121SMCStrategyXHKPVSignalConditions mTmpConditions[];
|
|
Copy(
|
|
mXHKPVConditionsCollection,
|
|
mTmpConditions //
|
|
);
|
|
X121SMCStrategyXHKPVSignalConditions mConditions;
|
|
for (int i = 0; i < conditionsCount; i++)
|
|
{
|
|
//
|
|
// Check Triggers ...
|
|
bool canTrigger = mTmpConditions[i].CanTrigger();
|
|
datetime triggerTime = mTmpConditions[i].triggerTime;
|
|
if (!canTrigger)
|
|
{
|
|
//
|
|
// Detect Signal Trigger ...
|
|
canTrigger = DetectX121SMCXHKPVSignalTrigger(
|
|
mTmpConditions[i],
|
|
symbol,
|
|
period,
|
|
mTriggerCycleHelper,
|
|
mDecisionCycleHelper,
|
|
mAnalyseCycleHelper,
|
|
mVerificationCycleHelper,
|
|
mConsolidationCycleHelper,
|
|
mVisionCycleHelper //
|
|
);
|
|
|
|
//
|
|
result = canTrigger;
|
|
if (!result)
|
|
{
|
|
//
|
|
bool isISetuped = mTmpConditions[i].IsSetuped();
|
|
if (!isISetuped)
|
|
{
|
|
//
|
|
ArrayRemove(
|
|
mXHKPVConditionsCollection,
|
|
i,
|
|
1 //
|
|
);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
//
|
|
triggerTime = mTmpConditions[i].triggerTime;
|
|
}
|
|
|
|
//
|
|
if (canTrigger)
|
|
{
|
|
//
|
|
selectedIndex = i;
|
|
mConditions = mTmpConditions[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValid(mConditions.setupTime) &&
|
|
HasDirection(mConditions.dir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Remove Selected Index from Main Collection ...
|
|
ArrayRemove(
|
|
mXHKPVConditionsCollection,
|
|
selectedIndex,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Check Signal Direction ...
|
|
isBullish = IsBullish(mConditions.dir);
|
|
isBearish = IsBearish(mConditions.dir);
|
|
result = isBullish ||
|
|
isBearish;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Issues Signal on Conditions ...
|
|
conditions.sl = mConditions.sl;
|
|
conditions.provider = providerStr;
|
|
conditions.signalDir = mConditions.dir;
|
|
conditions.target = mConditions.target;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// XOBPV Signal ...
|
|
bool DetectXOBPVSignal(
|
|
X121SMCStrategyConditions &conditions //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
int zIndex = 0;
|
|
int cIndex = zIndex + 1;
|
|
int pIndex = cIndex + 1;
|
|
int ppIndex = pIndex + 1;
|
|
|
|
//
|
|
string symbol = GetSymbol();
|
|
ENUM_TIMEFRAMES period = GetPeriod();
|
|
|
|
//
|
|
XOHCL zBar;
|
|
result = zBar.Init(
|
|
symbol,
|
|
period,
|
|
zIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL cBar;
|
|
result = cBar.Init(
|
|
symbol,
|
|
period,
|
|
cIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL pBar;
|
|
result = pBar.Init(
|
|
symbol,
|
|
period,
|
|
pIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double cLL = cBar.FindLowest(7, MODE_LOW);
|
|
double cHH = cBar.FindHighest(7, MODE_HIGH);
|
|
|
|
//
|
|
datetime cTime = TimeCurrent();
|
|
|
|
//
|
|
ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_XOBPV;
|
|
string providerStr = ToString(provider);
|
|
|
|
//
|
|
// Detect Setup Conditions ...
|
|
datetime setupTime = mXOBPVConditions.setupTime;
|
|
bool isSetuped = mXOBPVConditions.IsSetuped();
|
|
ENUM_X_DIRECTION setupDir = mXOBPVConditions.dir;
|
|
if (!isSetuped)
|
|
{
|
|
//
|
|
// Detect Signal Setup ...
|
|
isSetuped = DetectX121SMCXOBPVSignalSetup(
|
|
symbol,
|
|
period,
|
|
mXOBPVConditions,
|
|
mTriggerCycleHelper,
|
|
mDecisionCycleHelper,
|
|
mAnalyseCycleHelper,
|
|
mVerificationCycleHelper,
|
|
mConsolidationCycleHelper,
|
|
mVisionCycleHelper //
|
|
);
|
|
|
|
//
|
|
setupDir = mXOBPVConditions.dir;
|
|
setupTime = mXOBPVConditions.setupTime;
|
|
|
|
//
|
|
if (isSetuped)
|
|
{
|
|
//
|
|
int items = AddX121SMCXOBPVConditionsIfNotExists(
|
|
mXOBPVConditions,
|
|
mXOBPVConditionsCollection //
|
|
);
|
|
|
|
//
|
|
mXOBPVConditions.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
int conditionsCount = ArraySize(mXOBPVConditionsCollection);
|
|
result = IsValidSize(conditionsCount);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Looking For Conditions ...
|
|
int selectedIndex = 0;
|
|
X121SMCStrategyXOBPVSignalConditions mTmpConditions[];
|
|
Copy(
|
|
mXOBPVConditionsCollection,
|
|
mTmpConditions //
|
|
);
|
|
X121SMCStrategyXOBPVSignalConditions mConditions;
|
|
for (int i = 0; i < conditionsCount; i++)
|
|
{
|
|
//
|
|
// Check Triggers ...
|
|
bool canTrigger = mTmpConditions[i].CanTrigger();
|
|
datetime triggerTime = mTmpConditions[i].triggerTime;
|
|
if (!canTrigger)
|
|
{
|
|
//
|
|
// Detect Signal Trigger ...
|
|
canTrigger = DetectX121SMCXOBPVSignalTrigger(
|
|
mTmpConditions[i],
|
|
symbol,
|
|
period,
|
|
mTriggerCycleHelper,
|
|
mDecisionCycleHelper,
|
|
mAnalyseCycleHelper,
|
|
mVerificationCycleHelper,
|
|
mConsolidationCycleHelper,
|
|
mVisionCycleHelper //
|
|
);
|
|
|
|
//
|
|
result = canTrigger;
|
|
if (!result)
|
|
{
|
|
//
|
|
bool isISetuped = mTmpConditions[i].IsSetuped();
|
|
if (!isISetuped)
|
|
{
|
|
//
|
|
ArrayRemove(
|
|
mXOBPVConditionsCollection,
|
|
i,
|
|
1 //
|
|
);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
//
|
|
triggerTime = mTmpConditions[i].triggerTime;
|
|
}
|
|
|
|
//
|
|
if (canTrigger)
|
|
{
|
|
//
|
|
selectedIndex = i;
|
|
mConditions = mTmpConditions[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValid(mConditions.setupTime) &&
|
|
HasDirection(mConditions.dir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Remove Selected Index from Main Collection ...
|
|
ArrayRemove(
|
|
mXOBPVConditionsCollection,
|
|
selectedIndex,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Check Signal Direction ...
|
|
isBullish = IsBullish(mConditions.dir);
|
|
isBearish = IsBearish(mConditions.dir);
|
|
result = isBullish ||
|
|
isBearish;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Issues Signal on Conditions ...
|
|
conditions.sl = mConditions.sl;
|
|
conditions.provider = providerStr;
|
|
conditions.signalDir = mConditions.dir;
|
|
conditions.target = mConditions.target;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// XIOBPV Signal ...
|
|
bool DetectXIOBPVSignal(
|
|
X121SMCStrategyConditions &conditions //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
bool isBullish = false;
|
|
bool isBearish = false;
|
|
|
|
//
|
|
int zIndex = 0;
|
|
int cIndex = zIndex + 1;
|
|
int pIndex = cIndex + 1;
|
|
int ppIndex = pIndex + 1;
|
|
|
|
//
|
|
string symbol = GetSymbol();
|
|
ENUM_TIMEFRAMES period = GetPeriod();
|
|
|
|
//
|
|
XOHCL zBar;
|
|
result = zBar.Init(
|
|
symbol,
|
|
period,
|
|
zIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL cBar;
|
|
result = cBar.Init(
|
|
symbol,
|
|
period,
|
|
cIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL pBar;
|
|
result = pBar.Init(
|
|
symbol,
|
|
period,
|
|
pIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double cLL = cBar.FindLowest(7, MODE_LOW);
|
|
double cHH = cBar.FindHighest(7, MODE_HIGH);
|
|
|
|
//
|
|
datetime cTime = TimeCurrent();
|
|
|
|
//
|
|
ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_XIOBPV;
|
|
string providerStr = ToString(provider);
|
|
|
|
//
|
|
// Detect Setup Conditions ...
|
|
datetime setupTime = mXIOBPVConditions.setupTime;
|
|
bool isSetuped = mXIOBPVConditions.IsSetuped();
|
|
ENUM_X_DIRECTION setupDir = mXIOBPVConditions.dir;
|
|
if (!isSetuped)
|
|
{
|
|
//
|
|
// Detect Signal Setup ...
|
|
isSetuped = DetectX121SMCXIOBPVSignalSetup(
|
|
symbol,
|
|
period,
|
|
mXIOBPVConditions,
|
|
mTriggerCycleHelper,
|
|
mDecisionCycleHelper,
|
|
mAnalyseCycleHelper,
|
|
mVerificationCycleHelper,
|
|
mConsolidationCycleHelper,
|
|
mVisionCycleHelper //
|
|
);
|
|
|
|
//
|
|
setupDir = mXIOBPVConditions.dir;
|
|
setupTime = mXIOBPVConditions.setupTime;
|
|
|
|
//
|
|
if (isSetuped)
|
|
{
|
|
//
|
|
int items = AddX121SMCXIOBPVConditionsIfNotExists(
|
|
mXIOBPVConditions,
|
|
mXIOBPVConditionsCollection //
|
|
);
|
|
|
|
//
|
|
mXIOBPVConditions.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
int conditionsCount = ArraySize(mXIOBPVConditionsCollection);
|
|
result = IsValidSize(conditionsCount);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Looking For Conditions ...
|
|
int selectedIndex = 0;
|
|
X121SMCStrategyXIOBPVSignalConditions mTmpConditions[];
|
|
Copy(
|
|
mXIOBPVConditionsCollection,
|
|
mTmpConditions //
|
|
);
|
|
X121SMCStrategyXIOBPVSignalConditions mConditions;
|
|
for (int i = 0; i < conditionsCount; i++)
|
|
{
|
|
//
|
|
// Check Triggers ...
|
|
bool canTrigger = mTmpConditions[i].CanTrigger();
|
|
datetime triggerTime = mTmpConditions[i].triggerTime;
|
|
if (!canTrigger)
|
|
{
|
|
//
|
|
// Detect Signal Trigger ...
|
|
canTrigger = DetectX121SMCXIOBPVSignalTrigger(
|
|
mTmpConditions[i],
|
|
symbol,
|
|
period,
|
|
mTriggerCycleHelper,
|
|
mDecisionCycleHelper,
|
|
mAnalyseCycleHelper,
|
|
mVerificationCycleHelper,
|
|
mConsolidationCycleHelper,
|
|
mVisionCycleHelper //
|
|
);
|
|
|
|
//
|
|
result = canTrigger;
|
|
if (!result)
|
|
{
|
|
//
|
|
bool isISetuped = mTmpConditions[i].IsSetuped();
|
|
if (!isISetuped)
|
|
{
|
|
//
|
|
ArrayRemove(
|
|
mXIOBPVConditionsCollection,
|
|
i,
|
|
1 //
|
|
);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
//
|
|
triggerTime = mTmpConditions[i].triggerTime;
|
|
}
|
|
|
|
//
|
|
if (canTrigger)
|
|
{
|
|
//
|
|
selectedIndex = i;
|
|
mConditions = mTmpConditions[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValid(mConditions.setupTime) &&
|
|
HasDirection(mConditions.dir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Remove Selected Index from Main Collection ...
|
|
ArrayRemove(
|
|
mXIOBPVConditionsCollection,
|
|
selectedIndex,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
// Check Signal Direction ...
|
|
isBullish = IsBullish(mConditions.dir);
|
|
isBearish = IsBearish(mConditions.dir);
|
|
result = isBullish ||
|
|
isBearish;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Issues Signal on Conditions ...
|
|
conditions.sl = mConditions.sl;
|
|
conditions.provider = providerStr;
|
|
conditions.signalDir = mConditions.dir;
|
|
conditions.target = mConditions.target;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
const string X121SMCXHKPVToken = "X121XHKPV";
|
|
const string X121SMCXOBPVToken = "X121XOBPV";
|
|
const string X121SMCXIOBPVToken = "X121XIOBPV";
|
|
|
|
X_121_SMC_PROVIDER_XHKPV,
|
|
X_121_SMC_PROVIDER_XOBPV,
|
|
X_121_SMC_PROVIDER_XIOBPV,
|
|
|
|
|
|
//
|
|
case X_121_SMC_PROVIDER_XHKPV:
|
|
result = X121SMCXHKPVToken;
|
|
break;
|
|
|
|
//
|
|
case X_121_SMC_PROVIDER_XOBPV:
|
|
result = X121SMCXOBPVToken;
|
|
break;
|
|
|
|
//
|
|
case X_121_SMC_PROVIDER_XIOBPV:
|
|
result = X121SMCXIOBPVToken;
|
|
break;
|
|
|
|
else if (Contains(X121SMCXHKPVToken, value))
|
|
{
|
|
result = X_121_SMC_PROVIDER_XHKPV;
|
|
}
|
|
else if (Contains(X121SMCXOBPVToken, value))
|
|
{
|
|
result = X_121_SMC_PROVIDER_XOBPV;
|
|
}
|
|
else if (Contains(X121SMCXIOBPVToken, value))
|
|
{
|
|
result = X_121_SMC_PROVIDER_XIOBPV;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
/**
|
|
* Detect Market Structure Method 2 ...
|
|
*
|
|
* @param model: XMarketStructure instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectMarketStructure(
|
|
ENUM_X_DIRECTION &dir,
|
|
int pivotsCount = 3 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int barIndex = 0;
|
|
|
|
//
|
|
if (pivotsCount < 3)
|
|
{
|
|
pivotsCount = 3;
|
|
}
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
string symbol = GetSymbol();
|
|
ENUM_TIMEFRAMES period = GetPeriod();
|
|
|
|
//
|
|
int hpIndex = -1;
|
|
int hpIndexes[];
|
|
double hpValues[];
|
|
|
|
//
|
|
int lvIndex = -1;
|
|
int lvIndexes[];
|
|
double lvValues[];
|
|
|
|
//
|
|
for (int i = 0; i < pivotsCount; i++)
|
|
{
|
|
//
|
|
hpIndex = barIndex;
|
|
lvIndex = barIndex;
|
|
|
|
//
|
|
double lastHP = 0;
|
|
double lastLV = 0;
|
|
|
|
//
|
|
int hpCount = ArraySize(hpIndexes);
|
|
int lvCount = ArraySize(lvIndexes);
|
|
|
|
//
|
|
if (IsValidSize(hpCount))
|
|
{
|
|
//
|
|
lastHP = hpValues[hpCount - 1];
|
|
hpIndex = hpIndexes[hpCount - 1];
|
|
}
|
|
|
|
//
|
|
if (IsValidSize(lvCount))
|
|
{
|
|
//
|
|
lastLV = lvValues[lvCount - 1];
|
|
lvIndex = lvIndexes[lvCount - 1];
|
|
}
|
|
|
|
//
|
|
if (lastHP == 0)
|
|
{
|
|
//
|
|
lastHP = mX121Helper
|
|
.xpvHelper
|
|
.GetPeak(hpIndex);
|
|
}
|
|
|
|
//
|
|
if (lastLV == 0)
|
|
{
|
|
//
|
|
lastLV = mX121Helper
|
|
.xpvHelper
|
|
.GetVale(lvIndex);
|
|
}
|
|
|
|
//
|
|
int highestPeakIndex = -1;
|
|
double highesrPeak =
|
|
mX121Helper
|
|
.xpvHelper
|
|
.GetHigherPeak(
|
|
highestPeakIndex,
|
|
lastHP,
|
|
hpIndex //
|
|
);
|
|
if (IsValidIndex(highestPeakIndex))
|
|
{
|
|
//
|
|
Add(
|
|
highestPeakIndex,
|
|
hpIndexes //
|
|
);
|
|
|
|
//
|
|
Add(
|
|
highesrPeak,
|
|
hpValues //
|
|
);
|
|
}
|
|
|
|
//
|
|
int lowestValeIndex = -1;
|
|
double lowestVale =
|
|
mX121Helper
|
|
.xpvHelper
|
|
.GetLowerVale(
|
|
lowestValeIndex,
|
|
lastLV,
|
|
lvIndex //
|
|
);
|
|
if (IsValidIndex(lowestValeIndex))
|
|
{
|
|
//
|
|
Add(
|
|
lowestValeIndex,
|
|
lvIndexes //
|
|
);
|
|
|
|
//
|
|
Add(
|
|
lowestVale,
|
|
lvValues //
|
|
);
|
|
}
|
|
|
|
//
|
|
bool canBreak = ArraySize(hpIndexes) >= pivotsCount ||
|
|
ArraySize(lvIndexes) >= pivotsCount;
|
|
if (canBreak)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
ArrayReverse(hpValues);
|
|
ArrayReverse(hpIndexes);
|
|
int countHPs = ArraySize(hpIndexes);
|
|
|
|
//
|
|
ArrayReverse(lvValues);
|
|
ArrayReverse(lvIndexes);
|
|
int countLVs = ArraySize(lvIndexes);
|
|
|
|
//
|
|
bool isValidHPs = countHPs >= pivotsCount;
|
|
bool isValidLVs = countLVs >= pivotsCount;
|
|
|
|
//
|
|
result = isValidHPs ||
|
|
isValidLVs;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (isValidHPs && isValidLVs)
|
|
{
|
|
//
|
|
hpIndex = hpIndexes[countHPs - 1];
|
|
lvIndex = lvIndexes[countLVs - 1];
|
|
}
|
|
|
|
//
|
|
dir =
|
|
!isValidHPs && isValidLVs
|
|
? X_DIRECTION_BULLISH
|
|
: !isValidLVs && isValidHPs
|
|
? X_DIRECTION_BEARISH
|
|
: hpIndex < lvIndex
|
|
? X_DIRECTION_BEARISH
|
|
: lvIndex < hpIndex
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_ALL;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Order Blocks ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectOrderBlocks(
|
|
XCOrderBlock *&bullishOrderBlocks[],
|
|
XCOrderBlock *&bearishOrderBlocks[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
Clean(bullishOrderBlocks);
|
|
Clean(bearishOrderBlocks);
|
|
|
|
//
|
|
XPOIState state;
|
|
mPOIDetector.GetState(state);
|
|
bool isValid = state.IsValid() &&
|
|
state.HasChild();
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int bullOBsCount = DetectValidOrderBlocks(
|
|
X_DIRECTION_BULLISH,
|
|
state,
|
|
bullishOrderBlocks //
|
|
);
|
|
|
|
//
|
|
int bearOBsCount = DetectValidOrderBlocks(
|
|
X_DIRECTION_BEARISH,
|
|
state,
|
|
bearishOrderBlocks //
|
|
);
|
|
|
|
//
|
|
result = IsValidSize(bullOBsCount +
|
|
bearOBsCount);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Fair Value Gaps ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectFairValueGaps(
|
|
XCFVG *&bullishFairValueGaps[],
|
|
XCFVG *&bearishFairValueGaps[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
Clean(bullishFairValueGaps);
|
|
Clean(bearishFairValueGaps);
|
|
|
|
//
|
|
XPOIState state;
|
|
mPOIDetector.GetState(state);
|
|
bool isValid = state.IsValid() &&
|
|
state.HasChild();
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int bullFVGsCount = DetectValidFairValueGaps(
|
|
X_DIRECTION_BULLISH,
|
|
state,
|
|
bullishFairValueGaps //
|
|
);
|
|
|
|
//
|
|
int bearFVGsCount = DetectValidFairValueGaps(
|
|
X_DIRECTION_BEARISH,
|
|
state,
|
|
bearishFairValueGaps //
|
|
);
|
|
|
|
//
|
|
result = IsValidSize(bullFVGsCount +
|
|
bearFVGsCount);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Support Zones ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectSupportZones(
|
|
XCOrderBlock *&bullishOrderBlocks[],
|
|
XCFVG *&bullishFairValueGaps[],
|
|
XCSupportZone *&supportZones[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
Clean(supportZones);
|
|
|
|
//
|
|
int obsCount = ArraySize(bullishOrderBlocks);
|
|
int fvgsCount = ArraySize(bullishFairValueGaps);
|
|
|
|
//
|
|
XPOIState state;
|
|
mPOIDetector.GetState(state);
|
|
bool isValid = state.IsValid() &&
|
|
state.HasChild() &&
|
|
IsValidSize(obsCount + fvgsCount);
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int supportZonesCount = DetectValidSupportZones(
|
|
state,
|
|
bullishOrderBlocks,
|
|
bullishFairValueGaps,
|
|
supportZones //
|
|
);
|
|
|
|
//
|
|
result = IsValidSize(supportZonesCount);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Resistance Zones ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectResistanceZones(
|
|
XCOrderBlock *&bearishOrderBlocks[],
|
|
XCFVG *&bearishFairValueGaps[],
|
|
XCResistanceZone *&resistanceZones[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
Clean(resistanceZones);
|
|
|
|
//
|
|
int obsCount = ArraySize(bearishOrderBlocks);
|
|
int fvgsCount = ArraySize(bearishFairValueGaps);
|
|
|
|
//
|
|
XPOIState state;
|
|
mPOIDetector.GetState(state);
|
|
bool isValid = state.IsValid() &&
|
|
state.HasChild() &&
|
|
IsValidSize(obsCount + fvgsCount);
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int resistanceZonesCount = DetectValidResistanceZones(
|
|
state,
|
|
bearishOrderBlocks,
|
|
bearishFairValueGaps,
|
|
resistanceZones //
|
|
);
|
|
|
|
//
|
|
result = IsValidSize(resistanceZonesCount);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Demand Zones ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectDemandZones(
|
|
XCOrderBlock *&bullishOrderBlocks[],
|
|
XCFVG *&bullishFairValueGaps[],
|
|
XCDemandZone *&demandZones[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
Clean(demandZones);
|
|
|
|
//
|
|
int obsCount = ArraySize(bullishOrderBlocks);
|
|
int fvgsCount = ArraySize(bullishFairValueGaps);
|
|
|
|
//
|
|
XPOIState state;
|
|
mPOIDetector.GetState(state);
|
|
bool isValid = state.IsValid() &&
|
|
state.HasChild() &&
|
|
IsValidSize(obsCount + fvgsCount);
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int demandZonesCount = DetectValidDemandZones(
|
|
state,
|
|
bullishOrderBlocks,
|
|
bullishFairValueGaps,
|
|
demandZones //
|
|
);
|
|
|
|
//
|
|
result = IsValidSize(demandZonesCount);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Supply Zones ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectSupplyZones(
|
|
XCOrderBlock *&bearishOrderBlocks[],
|
|
XCFVG *&bearishFairValueGaps[],
|
|
XCSupplyZone *&supplyZones[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
Clean(supplyZones);
|
|
|
|
//
|
|
int obsCount = ArraySize(bearishOrderBlocks);
|
|
int fvgsCount = ArraySize(bearishFairValueGaps);
|
|
|
|
//
|
|
XPOIState state;
|
|
mPOIDetector.GetState(state);
|
|
bool isValid = state.IsValid() &&
|
|
state.HasChild() &&
|
|
IsValidSize(obsCount + fvgsCount);
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int supplyZonesCount = DetectValidSupplyZones(
|
|
state,
|
|
bearishOrderBlocks,
|
|
bearishFairValueGaps,
|
|
supplyZones //
|
|
);
|
|
|
|
//
|
|
result = IsValidSize(supplyZonesCount);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Count Prev Peak Repetition ...
|
|
*
|
|
* @param barIndex: Integer ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int CountPrevPeakRepetition(
|
|
int barIndex = 0//
|
|
) {
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (barIndex < 0) {
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
int index = barIndex + 1;
|
|
double value = mX121Helper.xpvHelper.GetPeak(index);
|
|
index++;
|
|
|
|
//
|
|
bool canContinue = true;
|
|
while(canContinue) {
|
|
//
|
|
double iValue = mX121Helper.xpvHelper.GetPeak(index);
|
|
|
|
//
|
|
canContinue = iValue == value;
|
|
if (canContinue) {
|
|
//
|
|
index++;
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Count Prev Vale Repetition ...
|
|
*
|
|
* @param barIndex: Integer ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int CountPrevValeRepetition(
|
|
int barIndex = 0//
|
|
) {
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (barIndex < 0) {
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
int index = barIndex + 1;
|
|
double value = mX121Helper.xpvHelper.GetVale(index);
|
|
index++;
|
|
|
|
//
|
|
bool canContinue = true;
|
|
while(canContinue) {
|
|
//
|
|
double iValue = mX121Helper.xpvHelper.GetVale(index);
|
|
|
|
//
|
|
canContinue = iValue == value;
|
|
if (canContinue) {
|
|
//
|
|
index++;
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Cycle State and Update it ...
|
|
*
|
|
* @param state: X121SMCCycleState instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool GetCycleState(X121SMCCycleState &state)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
string symbol = GetSymbol();
|
|
ENUM_TIMEFRAMES period = GetPeriod();
|
|
|
|
//
|
|
state.symbol = symbol;
|
|
state.period = period;
|
|
|
|
//
|
|
datetime cTime = TimeCurrent();
|
|
|
|
//
|
|
// Detect Order Block ...
|
|
|
|
//
|
|
bool hasBullishOBs = state.HasBullishOBs();
|
|
int bullishOBsCount = state.CountBullishOBs();
|
|
|
|
//
|
|
bool hasBearishOBs = state.HasBearishOBs();
|
|
int bearishOBsCount = state.CountBearishOBs();
|
|
|
|
//
|
|
bool hasOBs = hasBullishOBs &&
|
|
hasBearishOBs;
|
|
if (!hasOBs)
|
|
{
|
|
//
|
|
XCOrderBlock *bullishOBs[];
|
|
XCOrderBlock *bearishOBs[];
|
|
hasOBs = DetectOrderBlocks(
|
|
bullishOBs,
|
|
bearishOBs //
|
|
);
|
|
|
|
//
|
|
if (hasOBs &&
|
|
!hasBullishOBs)
|
|
{
|
|
//
|
|
Copy(
|
|
bullishOBs,
|
|
state.bullishOBs //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (hasOBs &&
|
|
!hasBearishOBs)
|
|
{
|
|
//
|
|
Copy(
|
|
bearishOBs,
|
|
state.bearishOBs //
|
|
);
|
|
}
|
|
|
|
//
|
|
hasBullishOBs = state.HasBullishOBs();
|
|
bullishOBsCount = state.CountBullishOBs();
|
|
|
|
//
|
|
hasBearishOBs = state.HasBearishOBs();
|
|
bearishOBsCount = state.CountBearishOBs();
|
|
}
|
|
|
|
//
|
|
// Update Order Blocks Time ...
|
|
if (hasOBs)
|
|
{
|
|
//
|
|
if (hasBullishOBs)
|
|
{
|
|
//
|
|
for (int i = 0; i < bullishOBsCount; i++)
|
|
{
|
|
state.bullishOBs[i].To(cTime);
|
|
}
|
|
}
|
|
|
|
//
|
|
if (hasBearishOBs)
|
|
{
|
|
//
|
|
for (int i = 0; i < bearishOBsCount; i++)
|
|
{
|
|
state.bearishOBs[i].To(cTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect Fair Value Gap ...
|
|
|
|
//
|
|
bool hasBullishFVGs = state.HasBullishFVGs();
|
|
int bullishFVGsCount = state.CountBullishFVGs();
|
|
|
|
//
|
|
bool hasBearishFVGs = state.HasBearishFVGs();
|
|
int bearishFVGsCount = state.CountBearishFVGs();
|
|
|
|
//
|
|
bool hasFVGs = hasBullishFVGs &&
|
|
hasBearishFVGs;
|
|
if (!hasFVGs)
|
|
{
|
|
//
|
|
XCFVG *bullishFVGs[];
|
|
XCFVG *bearishFVGs[];
|
|
hasFVGs = DetectFairValueGaps(
|
|
bullishFVGs,
|
|
bearishFVGs //
|
|
);
|
|
|
|
//
|
|
if (hasFVGs &&
|
|
!hasBullishFVGs)
|
|
{
|
|
//
|
|
Copy(
|
|
bullishFVGs,
|
|
state.bullishFVGs //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (hasFVGs &&
|
|
!hasBearishFVGs)
|
|
{
|
|
//
|
|
Copy(
|
|
bearishFVGs,
|
|
state.bearishFVGs //
|
|
);
|
|
}
|
|
|
|
//
|
|
hasBullishFVGs = state.HasBullishFVGs();
|
|
bullishFVGsCount = state.CountBullishFVGs();
|
|
|
|
//
|
|
hasBearishFVGs = state.HasBearishFVGs();
|
|
bearishFVGsCount = state.CountBearishFVGs();
|
|
}
|
|
|
|
//
|
|
// Update Fair Value Gaps Time ...
|
|
if (hasFVGs)
|
|
{
|
|
//
|
|
if (hasBullishFVGs)
|
|
{
|
|
//
|
|
for (int i = 0; i < bullishFVGsCount; i++)
|
|
{
|
|
state.bullishFVGs[i].To(cTime);
|
|
}
|
|
}
|
|
|
|
//
|
|
if (hasBearishFVGs)
|
|
{
|
|
//
|
|
for (int i = 0; i < bearishFVGsCount; i++)
|
|
{
|
|
state.bearishFVGs[i].To(cTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect Support Zones ...
|
|
|
|
//
|
|
bool hasSupportZones = state.HasSupportZones();
|
|
int supportZonesCount = state.CountSupportZones();
|
|
|
|
//
|
|
if (!hasSupportZones)
|
|
{
|
|
//
|
|
XCSupportZone *supportZones[];
|
|
hasSupportZones = DetectSupportZones(
|
|
state.bullishOBs,
|
|
state.bullishFVGs,
|
|
supportZones //
|
|
);
|
|
|
|
//
|
|
if (hasSupportZones)
|
|
{
|
|
//
|
|
Copy(
|
|
supportZones,
|
|
state.supportZones //
|
|
);
|
|
|
|
//
|
|
supportZonesCount = state.CountSupportZones();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update Support Zones Time ...
|
|
if (hasSupportZones)
|
|
{
|
|
//
|
|
for (int i = 0; i < supportZonesCount; i++)
|
|
{
|
|
state.supportZones[i].To(cTime);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect Demand Zones ...
|
|
|
|
//
|
|
bool hasDemandZones = state.HasDemandZones();
|
|
int demandZonesCount = state.CountDemandZones();
|
|
|
|
//
|
|
if (!hasDemandZones)
|
|
{
|
|
//
|
|
XCDemandZone *demandZones[];
|
|
hasDemandZones = DetectDemandZones(
|
|
state.bullishOBs,
|
|
state.bullishFVGs,
|
|
demandZones //
|
|
);
|
|
|
|
//
|
|
if (hasDemandZones)
|
|
{
|
|
//
|
|
Copy(
|
|
demandZones,
|
|
state.demandZones //
|
|
);
|
|
|
|
//
|
|
demandZonesCount = state.CountDemandZones();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update Support Zones Time ...
|
|
if (hasDemandZones)
|
|
{
|
|
//
|
|
for (int i = 0; i < demandZonesCount; i++)
|
|
{
|
|
state.demandZones[i].To(cTime);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect Resistance Zones ...
|
|
|
|
//
|
|
bool hasResistanceZones = state.HasResistanceZones();
|
|
int resistanceZonesCount = state.CountResistanceZones();
|
|
|
|
//
|
|
if (!hasResistanceZones)
|
|
{
|
|
//
|
|
XCResistanceZone *resistanceZones[];
|
|
hasResistanceZones = DetectResistanceZones(
|
|
state.bearishOBs,
|
|
state.bearishFVGs,
|
|
resistanceZones //
|
|
);
|
|
|
|
//
|
|
if (hasResistanceZones)
|
|
{
|
|
//
|
|
for (int i = 0; i < ArraySize(resistanceZones); i++)
|
|
{
|
|
resistanceZones[i].To(cTime);
|
|
}
|
|
|
|
//
|
|
Copy(
|
|
resistanceZones,
|
|
state.resistanceZones //
|
|
);
|
|
|
|
//
|
|
resistanceZonesCount = state.CountResistanceZones();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update Resistance Zones Time ...
|
|
if (hasResistanceZones)
|
|
{
|
|
//
|
|
for (int i = 0; i < resistanceZonesCount; i++)
|
|
{
|
|
state.resistanceZones[i].To(cTime);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Detect Supply Zones ...
|
|
|
|
//
|
|
bool hasSupplyZones = state.HasSupplyZones();
|
|
int supplyZonesCount = state.CountSupplyZones();
|
|
|
|
//
|
|
if (!hasSupplyZones)
|
|
{
|
|
//
|
|
XCSupplyZone *supplyZones[];
|
|
hasSupplyZones = DetectSupplyZones(
|
|
state.bearishOBs,
|
|
state.bearishFVGs,
|
|
supplyZones //
|
|
);
|
|
|
|
//
|
|
if (hasSupplyZones)
|
|
{
|
|
//
|
|
Copy(
|
|
supplyZones,
|
|
state.supplyZones //
|
|
);
|
|
|
|
//
|
|
supplyZonesCount = state.CountSupplyZones();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update Resistance Zones Time ...
|
|
if (hasSupplyZones)
|
|
{
|
|
//
|
|
for (int i = 0; i < supplyZonesCount; i++)
|
|
{
|
|
state.supplyZones[i].To(cTime);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = state.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Model Cycle State ...
|
|
struct X121SMCCycleState
|
|
{
|
|
//
|
|
// Props ...
|
|
string symbol;
|
|
ENUM_TIMEFRAMES period;
|
|
|
|
//
|
|
// Bullish ...
|
|
XCFVG *bullishFVGs[];
|
|
XCOrderBlock *bullishOBs[];
|
|
XCDemandZone *demandZones[];
|
|
XCSupportZone *supportZones[];
|
|
|
|
//
|
|
// Bearish ...
|
|
XCFVG *bearishFVGs[];
|
|
XCOrderBlock *bearishOBs[];
|
|
XCSupplyZone *supplyZones[];
|
|
XCResistanceZone *resistanceZones[];
|
|
|
|
//
|
|
// Constructor ...
|
|
X121SMCCycleState()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
/**
|
|
* Cleanup Model ...
|
|
*/
|
|
void Clean()
|
|
{
|
|
//
|
|
symbol = NULL;
|
|
period = NULL;
|
|
|
|
//
|
|
Clean(bullishFVGs);
|
|
Clean(bullishOBs);
|
|
Clean(demandZones);
|
|
Clean(supportZones);
|
|
|
|
//
|
|
Clean(bearishFVGs);
|
|
Clean(bearishOBs);
|
|
Clean(supplyZones);
|
|
Clean(resistanceZones);
|
|
|
|
//
|
|
ZeroMemory(this);
|
|
}
|
|
|
|
/**
|
|
* Validate Model ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(symbol) &&
|
|
IsValid(period) &&
|
|
(
|
|
//
|
|
(HasBullishOBs() &&
|
|
(HasBullishFVGs() ||
|
|
HasSupportZones() ||
|
|
HasDemandZones()))
|
|
//
|
|
||
|
|
(HasBearishOBs() &&
|
|
(HasSupplyZones() ||
|
|
HasBearishFVGs() ||
|
|
HasResistanceZones()))
|
|
//
|
|
)
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int CountBullishOBs()
|
|
{
|
|
return ArraySize(bullishOBs);
|
|
}
|
|
|
|
//
|
|
bool HasBullishOBs()
|
|
{
|
|
return IsValidSize(CountBullishOBs());
|
|
}
|
|
|
|
//
|
|
int CountBearishOBs()
|
|
{
|
|
return ArraySize(bearishOBs);
|
|
}
|
|
|
|
//
|
|
bool HasBearishOBs()
|
|
{
|
|
return IsValidSize(CountBearishOBs());
|
|
}
|
|
|
|
//
|
|
int CountSupportZones()
|
|
{
|
|
return ArraySize(supportZones);
|
|
}
|
|
|
|
//
|
|
bool HasSupportZones()
|
|
{
|
|
return IsValidSize(CountSupportZones());
|
|
}
|
|
|
|
//
|
|
int CountResistanceZones()
|
|
{
|
|
return ArraySize(resistanceZones);
|
|
}
|
|
|
|
//
|
|
bool HasResistanceZones()
|
|
{
|
|
return IsValidSize(CountResistanceZones());
|
|
}
|
|
|
|
//
|
|
int CountDemandZones()
|
|
{
|
|
return ArraySize(demandZones);
|
|
}
|
|
|
|
//
|
|
bool HasDemandZones()
|
|
{
|
|
return IsValidSize(CountDemandZones());
|
|
}
|
|
|
|
//
|
|
int CountSupplyZones()
|
|
{
|
|
return ArraySize(supplyZones);
|
|
}
|
|
|
|
//
|
|
bool HasSupplyZones()
|
|
{
|
|
return IsValidSize(CountSupplyZones());
|
|
}
|
|
|
|
//
|
|
int CountBullishFVGs()
|
|
{
|
|
return ArraySize(bullishFVGs);
|
|
}
|
|
|
|
//
|
|
bool HasBullishFVGs()
|
|
{
|
|
return IsValidSize(CountBullishFVGs());
|
|
}
|
|
|
|
//
|
|
int CountBearishFVGs()
|
|
{
|
|
return ArraySize(bearishFVGs);
|
|
}
|
|
|
|
//
|
|
bool HasBearishFVGs()
|
|
{
|
|
return IsValidSize(CountBearishFVGs());
|
|
}
|
|
|
|
//
|
|
bool GetOldestOB(
|
|
XCOrderBlock *&orderBlock //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
orderBlock = NULL;
|
|
|
|
//
|
|
bool hasBullishOB = HasBullishOBs();
|
|
bool hasBearishOB = HasBearishOBs();
|
|
result = hasBullishOB ||
|
|
hasBearishOB;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int iBullOBIDX = -1;
|
|
bool iHasBullOB = false;
|
|
XCOrderBlock *iBullOB = NULL;
|
|
if (hasBullishOB)
|
|
{
|
|
//
|
|
XCZone *iZones[];
|
|
ToZone(
|
|
bullishOBs,
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iBullOBIDX = GetOldest(
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iHasBullOB = IsValidIndex(iBullOBIDX);
|
|
if (iHasBullOB)
|
|
{
|
|
iBullOB = bullishOBs[iBullOBIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
int iBearOBIDX = -1;
|
|
bool iHasBearOB = false;
|
|
XCOrderBlock *iBearOB = NULL;
|
|
if (hasBearishOB)
|
|
{
|
|
//
|
|
XCZone *iZones[];
|
|
ToZone(
|
|
bearishOBs,
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iBearOBIDX = GetOldest(
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iHasBearOB = IsValidIndex(iBearOBIDX);
|
|
if (iHasBearOB)
|
|
{
|
|
iBearOB = bearishOBs[iBearOBIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iHasBullOB)
|
|
{
|
|
orderBlock = iBullOB;
|
|
}
|
|
|
|
//
|
|
if (iHasBearOB)
|
|
{
|
|
//
|
|
bool canSet = orderBlock == NULL ||
|
|
orderBlock.From() > iBearOB.From();
|
|
if (canSet)
|
|
{
|
|
orderBlock = iBearOB;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = orderBlock != NULL &&
|
|
orderBlock.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool GetYoungestOB(
|
|
XCOrderBlock *&orderBlock //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
orderBlock = NULL;
|
|
|
|
//
|
|
bool hasBullishOB = HasBullishOBs();
|
|
bool hasBearishOB = HasBearishOBs();
|
|
result = hasBullishOB ||
|
|
hasBearishOB;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int iBullOBIDX = -1;
|
|
bool iHasBullOB = false;
|
|
XCOrderBlock *iBullOB = NULL;
|
|
if (hasBullishOB)
|
|
{
|
|
//
|
|
XCZone *iZones[];
|
|
ToZone(
|
|
bullishOBs,
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iBullOBIDX = GetYoungest(
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iHasBullOB = IsValidIndex(iBullOBIDX);
|
|
if (iHasBullOB)
|
|
{
|
|
iBullOB = bullishOBs[iBullOBIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
int iBearOBIDX = -1;
|
|
bool iHasBearOB = false;
|
|
XCOrderBlock *iBearOB = NULL;
|
|
if (hasBearishOB)
|
|
{
|
|
//
|
|
XCZone *iZones[];
|
|
ToZone(
|
|
bearishOBs,
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iBearOBIDX = GetYoungest(
|
|
iZones //
|
|
);
|
|
|
|
//
|
|
iHasBearOB = IsValidIndex(iBearOBIDX);
|
|
if (iHasBearOB)
|
|
{
|
|
iBearOB = bearishOBs[iBearOBIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
if (iHasBullOB)
|
|
{
|
|
orderBlock = iBullOB;
|
|
}
|
|
|
|
//
|
|
if (iHasBearOB)
|
|
{
|
|
//
|
|
bool canSet = orderBlock == NULL ||
|
|
orderBlock.From() < iBearOB.From();
|
|
if (canSet)
|
|
{
|
|
orderBlock = iBearOB;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = orderBlock != NULL &&
|
|
orderBlock.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
|
|
/**
|
|
* Detect Price inside Box ...
|
|
*
|
|
* @param box: XBoxZone instance Reference, Founded Price Inside Box ...
|
|
* @param orderBlock: XCOrderBlock pointer Reference, Founded Price Inside Order Block ...
|
|
* @param xConditions: X121Conditions instance Reference, provides Market Conditions ...
|
|
* @param state: X121SMCCycleState instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool DetectPriceInsideBox(
|
|
XBoxZone &box, // Price Inside Bo ...
|
|
XCOrderBlock *&orderBlock, // Price Inside Order Block ...
|
|
X121Conditions &xConditions, // X121Conditions for Validation ...
|
|
X121SMCCycleState &state // Cycle State ...
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
box.Clean();
|
|
|
|
//
|
|
string symbol = state.symbol;
|
|
ENUM_TIMEFRAMES period = state.period;
|
|
|
|
//
|
|
box.symbol = symbol;
|
|
box.period = period;
|
|
|
|
//
|
|
result = state.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detect Price Inside Order Block ...
|
|
|
|
//
|
|
bool hasBullishOBs = state.HasBullishOBs();
|
|
int bullishOBsCount = state.CountBullishOBs();
|
|
|
|
//
|
|
bool hasBearishOBs = state.HasBearishOBs();
|
|
int bearishOBsCount = state.CountBearishOBs();
|
|
|
|
//
|
|
bool hasOBs =
|
|
//
|
|
hasBullishOBs ||
|
|
hasBearishOBs
|
|
//
|
|
;
|
|
result = hasOBs;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool hasPriceInsideOB = false;
|
|
XCOrderBlock *priceInsideOB = NULL;
|
|
ENUM_X_DIRECTION boxDir = X_DIRECTION_NONE;
|
|
|
|
//
|
|
if (hasBullishOBs &&
|
|
!hasPriceInsideOB)
|
|
{
|
|
//
|
|
for (int i = 0; i < bullishOBsCount; i++)
|
|
{
|
|
//
|
|
XCOrderBlock *iOb = state.bullishOBs[i];
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
xConditions.valesBuffer[1],
|
|
(XCZone *)iOb //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
priceInsideOB = iOb;
|
|
hasPriceInsideOB = true;
|
|
boxDir = X_DIRECTION_BULLISH;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (hasBearishOBs &&
|
|
!hasPriceInsideOB)
|
|
{
|
|
//
|
|
for (int i = 0; i < bearishOBsCount; i++)
|
|
{
|
|
//
|
|
XCOrderBlock *iOb = state.bearishOBs[i];
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
xConditions.peaksBuffer[1],
|
|
(XCZone *)iOb //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
priceInsideOB = iOb;
|
|
hasPriceInsideOB = true;
|
|
boxDir = X_DIRECTION_BEARISH;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (hasPriceInsideOB)
|
|
{
|
|
//
|
|
orderBlock = priceInsideOB;
|
|
boxDir = priceInsideOB.IsBullish()
|
|
? X_DIRECTION_BULLISH
|
|
: priceInsideOB.IsBearish()
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
}
|
|
|
|
//
|
|
bool hasBullishFVGs = state.HasBullishFVGs();
|
|
bool hasBearishFVGs = state.HasBearishFVGs();
|
|
bool hasDemandZones = state.HasDemandZones();
|
|
bool hasSupplyZones = state.HasSupplyZones();
|
|
bool hasSupportZones = state.HasSupportZones();
|
|
bool hasResistanceZones = state.HasResistanceZones();
|
|
|
|
//
|
|
bool hasBullishZones =
|
|
//
|
|
hasBullishFVGs ||
|
|
hasDemandZones ||
|
|
hasSupportZones
|
|
//
|
|
;
|
|
|
|
//
|
|
bool hasBearishZones =
|
|
//
|
|
hasBearishFVGs ||
|
|
hasSupplyZones ||
|
|
hasResistanceZones
|
|
//
|
|
;
|
|
|
|
//
|
|
bool hasPropperZones =
|
|
//
|
|
IsBullish(boxDir)
|
|
? hasBullishZones
|
|
: IsBearish(boxDir)
|
|
? hasBearishZones
|
|
: false
|
|
//
|
|
;
|
|
|
|
//
|
|
if (!hasPropperZones &&
|
|
hasPriceInsideOB)
|
|
{
|
|
//
|
|
// Use Price Inside OB as Box ...
|
|
box.dir = boxDir;
|
|
box.to = priceInsideOB.To();
|
|
box.from = priceInsideOB.From();
|
|
box.upper = priceInsideOB.Upper();
|
|
box.lower = priceInsideOB.Lower();
|
|
}
|
|
else if (hasPropperZones &&
|
|
hasPriceInsideOB)
|
|
{
|
|
//
|
|
// Detect Validate Zones ...
|
|
int count = 0;
|
|
XBoxZone boxes[];
|
|
double upper = 0;
|
|
double lower = 0;
|
|
double price = 0;
|
|
datetime to = NULL;
|
|
datetime from = NULL;
|
|
ENUM_X_DIRECTION dir = X_DIRECTION_NONE;
|
|
if (IsBullish(boxDir))
|
|
{
|
|
//
|
|
double price = xConditions.valesBuffer[1];
|
|
dir = X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
// Bullish FVG ...
|
|
count = state.CountBullishFVGs();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCFVG *iFVG = state.bullishFVGs[i];
|
|
|
|
//
|
|
to = iFVG.To();
|
|
from = iFVG.From();
|
|
upper = iFVG.Upper();
|
|
lower = iFVG.Lower();
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
price,
|
|
upper,
|
|
lower //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
|
|
//
|
|
iBox.dir = dir;
|
|
iBox.symbol = symbol;
|
|
iBox.period = period;
|
|
|
|
//
|
|
iBox.to = to;
|
|
iBox.from = from;
|
|
iBox.upper = upper;
|
|
iBox.lower = lower;
|
|
|
|
//
|
|
if (iBox.IsValid())
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
boxes //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand Zones ...
|
|
count = state.CountDemandZones();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCDemandZone *iDemand = state.demandZones[i];
|
|
|
|
//
|
|
to = iDemand.To();
|
|
from = iDemand.From();
|
|
upper = iDemand.Upper();
|
|
lower = iDemand.Lower();
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
price,
|
|
upper,
|
|
lower //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
|
|
//
|
|
iBox.dir = dir;
|
|
iBox.symbol = symbol;
|
|
iBox.period = period;
|
|
|
|
//
|
|
iBox.to = to;
|
|
iBox.from = from;
|
|
iBox.upper = upper;
|
|
iBox.lower = lower;
|
|
|
|
//
|
|
if (iBox.IsValid())
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
boxes //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support Zones ...
|
|
count = state.CountSupportZones();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCSupportZone *iSupport = state.supportZones[i];
|
|
|
|
//
|
|
to = iSupport.To();
|
|
from = iSupport.From();
|
|
upper = iSupport.Upper();
|
|
lower = iSupport.Lower();
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
price,
|
|
upper,
|
|
lower //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
|
|
//
|
|
iBox.dir = dir;
|
|
iBox.symbol = symbol;
|
|
iBox.period = period;
|
|
|
|
//
|
|
iBox.to = to;
|
|
iBox.from = from;
|
|
iBox.upper = upper;
|
|
iBox.lower = lower;
|
|
|
|
//
|
|
if (iBox.IsValid())
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
boxes //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
double price = xConditions.peaksBuffer[1];
|
|
dir = X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
// Bearish FVG ...
|
|
count = state.CountBearishFVGs();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCFVG *iFVG = state.bearishFVGs[i];
|
|
|
|
//
|
|
to = iFVG.To();
|
|
from = iFVG.From();
|
|
upper = iFVG.Upper();
|
|
lower = iFVG.Lower();
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
price,
|
|
upper,
|
|
lower //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
|
|
//
|
|
iBox.dir = dir;
|
|
iBox.symbol = symbol;
|
|
iBox.period = period;
|
|
|
|
//
|
|
iBox.to = to;
|
|
iBox.from = from;
|
|
iBox.upper = upper;
|
|
iBox.lower = lower;
|
|
|
|
//
|
|
if (iBox.IsValid())
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
boxes //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Supply Zones ...
|
|
count = state.CountSupplyZones();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCSupplyZone *iSupply = state.supplyZones[i];
|
|
|
|
//
|
|
to = iSupply.To();
|
|
from = iSupply.From();
|
|
upper = iSupply.Upper();
|
|
lower = iSupply.Lower();
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
price,
|
|
upper,
|
|
lower //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
|
|
//
|
|
iBox.dir = dir;
|
|
iBox.symbol = symbol;
|
|
iBox.period = period;
|
|
|
|
//
|
|
iBox.to = to;
|
|
iBox.from = from;
|
|
iBox.upper = upper;
|
|
iBox.lower = lower;
|
|
|
|
//
|
|
if (iBox.IsValid())
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
boxes //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand Zones ...
|
|
count = state.CountResistanceZones();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XCResistanceZone *iResistance = state.resistanceZones[i];
|
|
|
|
//
|
|
to = iResistance.To();
|
|
from = iResistance.From();
|
|
upper = iResistance.Upper();
|
|
lower = iResistance.Lower();
|
|
|
|
//
|
|
bool isInside = IsPriceInsideZone(
|
|
price,
|
|
upper,
|
|
lower //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
|
|
//
|
|
iBox.dir = dir;
|
|
iBox.symbol = symbol;
|
|
iBox.period = period;
|
|
|
|
//
|
|
iBox.to = to;
|
|
iBox.from = from;
|
|
iBox.upper = upper;
|
|
iBox.lower = lower;
|
|
|
|
//
|
|
if (iBox.IsValid())
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
boxes //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
bool hasBoxes = IsValidSize(boxes);
|
|
if (hasBoxes)
|
|
{
|
|
//
|
|
// Filter Boxes ...
|
|
for (int i = 0; i < boxesCount; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = boxes[i];
|
|
|
|
//
|
|
// Direction ...
|
|
if (!HasDirection(box.dir) || box.dir != iBox.dir)
|
|
{
|
|
box.dir = iBox.dir;
|
|
}
|
|
|
|
//
|
|
// Upper ...
|
|
if (box.upper == 0 || box.upper < iBox.upper)
|
|
{
|
|
box.upper = iBox.upper;
|
|
}
|
|
|
|
//
|
|
// Lower ...
|
|
if (box.lower == 0 || box.lower < iBox.lower)
|
|
{
|
|
box.lower = iBox.lower;
|
|
}
|
|
|
|
//
|
|
// To ...
|
|
if (!IsValid(box.to) || box.to < iBox.to)
|
|
{
|
|
box.to = iBox.to;
|
|
}
|
|
|
|
//
|
|
// From ...
|
|
if (!IsValid(box.from) || box.from > iBox.from)
|
|
{
|
|
box.from = iBox.from;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Use Price Inside OB as Box ...
|
|
box.dir = boxDir;
|
|
box.to = priceInsideOB.To();
|
|
box.from = priceInsideOB.From();
|
|
box.upper = priceInsideOB.Upper();
|
|
box.lower = priceInsideOB.Lower();
|
|
}
|
|
}
|
|
|
|
//
|
|
result = box.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Draw Cycle State ...
|
|
*
|
|
* @param state: X121SMCCyleState instance Reference ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int DrawCycleState(
|
|
X121SMCCycleState &state,
|
|
XCBaseObject *&drawnObjects[],
|
|
bool drawOrderBlocks = true,
|
|
bool drawFairValueGaps = true,
|
|
bool drawSupplyAndDemandZones = false,
|
|
bool drawSupportAndResistanceZones = false //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Order Blocks ...
|
|
if (drawOrderBlocks)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bool hasBullishOBs = state.HasBullishOBs();
|
|
int bullishOBsCount = state.CountBullishOBs();
|
|
if (hasBullishOBs)
|
|
{
|
|
//
|
|
for (int i = 0; i < bullishOBsCount; i++)
|
|
{
|
|
//
|
|
XCOrderBlock *iOb = state.bullishOBs[i];
|
|
|
|
//
|
|
XCBullishOrderBlockObject *iObObj;
|
|
bool isCreated = mPOIDrawer
|
|
.CreateBullishOrderBlock(
|
|
iOb,
|
|
iObObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
Add(
|
|
(XCBaseObject *)iObObj,
|
|
drawnObjects //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
bool hasBearishOBs = state.HasBearishOBs();
|
|
int bearishOBsCount = state.CountBearishOBs();
|
|
if (hasBearishOBs)
|
|
{
|
|
//
|
|
for (int i = 0; i < bearishOBsCount; i++)
|
|
{
|
|
//
|
|
XCOrderBlock *iOb = state.bearishOBs[i];
|
|
|
|
//
|
|
XCBearishOrderBlockObject *iObObj;
|
|
bool isCreated = mPOIDrawer
|
|
.CreateBearishOrderBlock(
|
|
iOb,
|
|
iObObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
Add(
|
|
(XCBaseObject *)iObObj,
|
|
drawnObjects //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
if (drawFairValueGaps)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bool hasBullishFVGs = state.HasBullishFVGs();
|
|
int bullishFVGsCount = state.CountBullishFVGs();
|
|
if (hasBullishFVGs)
|
|
{
|
|
//
|
|
for (int i = 0; i < bullishFVGsCount; i++)
|
|
{
|
|
//
|
|
XCFVG *iFVG = state.bullishFVGs[i];
|
|
|
|
//
|
|
XCBullishFairValueGapObject *iFVGObj;
|
|
bool isCreated = mPOIDrawer
|
|
.CreateBullishFairValueGap(
|
|
iFVG,
|
|
iFVGObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
iFVGObj.ZoneColor(clrLime);
|
|
|
|
//
|
|
Add(
|
|
(XCBaseObject *)iFVGObj,
|
|
drawnObjects //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
bool hasBearishFVGs = state.HasBearishFVGs();
|
|
int bearishFVGsCount = state.CountBearishFVGs();
|
|
if (hasBearishFVGs)
|
|
{
|
|
//
|
|
for (int i = 0; i < bearishFVGsCount; i++)
|
|
{
|
|
//
|
|
XCFVG *iFVG = state.bearishFVGs[i];
|
|
|
|
//
|
|
XCBearishFairValueGapObject *iFVGObj;
|
|
bool isCreated = mPOIDrawer
|
|
.CreateBearishFairValueGap(
|
|
iFVG,
|
|
iFVGObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
iFVGObj.ZoneColor(clrRed);
|
|
|
|
//
|
|
Add(
|
|
(XCBaseObject *)iFVGObj,
|
|
drawnObjects //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support and Resistance Zones ...
|
|
if (drawSupportAndResistanceZones)
|
|
{
|
|
//
|
|
// Support Zones ...
|
|
bool hasSupportZones = state.HasSupportZones();
|
|
int supportZonesCount = state.CountSupportZones();
|
|
if (hasSupportZones)
|
|
{
|
|
//
|
|
for (int i = 0; i < supportZonesCount; i++)
|
|
{
|
|
//
|
|
XCSupportZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer
|
|
.CreateSupportZone(
|
|
state.supportZones[i],
|
|
iObj //
|
|
);
|
|
|
|
//
|
|
if (isCreated)
|
|
{
|
|
//
|
|
iObj.ZoneColor(clrDarkSeaGreen);
|
|
|
|
//
|
|
Add(
|
|
(XCBaseObject *)iObj,
|
|
drawnObjects //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistance Zones ...
|
|
bool hasResistanceZones = state.HasResistanceZones();
|
|
int resistanceZonesCount = state.CountResistanceZones();
|
|
if (hasResistanceZones)
|
|
{
|
|
//
|
|
for (int i = 0; i < resistanceZonesCount; i++)
|
|
{
|
|
//
|
|
XCResistanceZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer
|
|
.CreateResistanceZone(
|
|
state.resistanceZones[i],
|
|
iObj //
|
|
);
|
|
|
|
//
|
|
if (isCreated)
|
|
{
|
|
//
|
|
iObj.ZoneColor(clrSaddleBrown);
|
|
|
|
//
|
|
Add(
|
|
(XCBaseObject *)iObj,
|
|
drawnObjects //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Supply and Demand Zones ...
|
|
if (drawSupplyAndDemandZones)
|
|
{
|
|
//
|
|
// Demand Zones ...
|
|
bool hasDemandZones = state.HasDemandZones();
|
|
int demandZonesCount = state.CountDemandZones();
|
|
if (hasDemandZones)
|
|
{
|
|
//
|
|
for (int i = 0; i < demandZonesCount; i++)
|
|
{
|
|
//
|
|
XCDemandZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer
|
|
.CreateDemandZone(
|
|
state.demandZones[i],
|
|
iObj //
|
|
);
|
|
|
|
//
|
|
if (isCreated)
|
|
{
|
|
//
|
|
iObj.ZoneColor(clrDarkTurquoise);
|
|
|
|
//
|
|
Add(
|
|
(XCBaseObject *)iObj,
|
|
drawnObjects //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Supply Zones ...
|
|
bool hasSupplyZones = state.HasSupplyZones();
|
|
int supplyZonesCount = state.CountSupplyZones();
|
|
if (hasSupplyZones)
|
|
{
|
|
//
|
|
for (int i = 0; i < supplyZonesCount; i++)
|
|
{
|
|
//
|
|
XCSupplyZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer
|
|
.CreateSupplyZone(
|
|
state.supplyZones[i],
|
|
iObj //
|
|
);
|
|
|
|
//
|
|
if (isCreated)
|
|
{
|
|
//
|
|
iObj.ZoneColor(clrChocolate);
|
|
|
|
//
|
|
Add(
|
|
(XCBaseObject *)iObj,
|
|
drawnObjects //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(drawnObjects);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//
|
|
bool isLong = analyseXConditions.isStrSwitchedToBullish &&
|
|
decisionXConditions.isCheBullish &&
|
|
decisionXConditions.isStrBullish;
|
|
bool isShort = analyseXConditions.isStrSwitchedToBearish &&
|
|
decisionXConditions.isCheBearish &&
|
|
decisionXConditions.isStrBearish;
|
|
|
|
//
|
|
result = isLong ||
|
|
isShort;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XRR rr;
|
|
|
|
//
|
|
double sl =
|
|
isLong
|
|
? decisionXConditions.strBuffer[1] - 10 * points
|
|
: decisionXConditions.strBuffer[1] + 10 * points;
|
|
|
|
//
|
|
ENUM_X_DIRECTION dir =
|
|
isLong
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
ENUM_X_POSITION_TYPES type =
|
|
isLong
|
|
? X_POSITION_TYPE_LONG
|
|
: X_POSITION_TYPE_SHORT;
|
|
|
|
//
|
|
double entry = GetEntry(symbol, dir);
|
|
|
|
//
|
|
result = rr.Init(
|
|
symbol,
|
|
period,
|
|
sl,
|
|
entry,
|
|
type //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XCRRObject *iRRObj;
|
|
result = visionCycleHelper
|
|
.mPOIDrawer
|
|
.CreateRR(
|
|
rr,
|
|
iRRObj //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//
|
|
// 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(),
|
|
iBreakerBar.period,
|
|
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[];
|
|
XCFVG *iOBFVG = NULL;
|
|
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 ...
|
|
);
|
|
|
|
//
|
|
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);
|
|
|
|
//
|
|
if (iOBFVG == NULL)
|
|
{
|
|
iOBFVG = jFVG;
|
|
}
|
|
|
|
//
|
|
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.fvg = iOBFVG;
|
|
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[];
|
|
XCFVG *iOBFVG = NULL;
|
|
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 ...
|
|
);
|
|
|
|
//
|
|
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);
|
|
|
|
//
|
|
if (iOBFVG == NULL)
|
|
{
|
|
iOBFVG = jFVG;
|
|
}
|
|
|
|
//
|
|
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.fvg = iOBFVG;
|
|
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;
|
|
// }
|
|
|
|
//
|
|
// TODO: ...
|
|
|
|
//
|
|
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];
|
|
ENUM_X_DIRECTION forDir = iOB.GetDirection();
|
|
|
|
//
|
|
XOHCL startedBar;
|
|
ENUM_X_DIRECTION startedDir;
|
|
bool isStarted = iOB.IsStarted(
|
|
forDir,
|
|
startedBar,
|
|
startedDir //
|
|
);
|
|
if (isStarted)
|
|
{
|
|
//
|
|
string name = "Start_" + iOB.GetTag();
|
|
ulong chartID = drawer.ChartIdentification();
|
|
int subWindow = drawer.SubWindowIdentification();
|
|
|
|
//
|
|
CChartObjectVLine *vLine;
|
|
vLine = new CChartObjectVLine();
|
|
bool isCreated = vLine.Create(
|
|
chartID,
|
|
name,
|
|
subWindow,
|
|
startedBar.time //
|
|
);
|
|
|
|
//
|
|
if (isCreated)
|
|
{
|
|
vLine.Color(clrYellow);
|
|
}
|
|
}
|
|
|
|
//
|
|
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 //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
//
|
|
// Test FVg Rewards ...
|
|
// for (int i = 0; i < testsCount; i++)
|
|
// {
|
|
// //
|
|
// XOBTest iTest = tests[i];
|
|
|
|
// //
|
|
// double iReward = 0;
|
|
// datetime iRewardedAt = NULL;
|
|
// bool isRewarded = TestFVG(
|
|
// iTest.fvg,
|
|
// iReward,
|
|
// iRewardedAt,
|
|
// //
|
|
// drawer,
|
|
// ttfState.period //
|
|
// );
|
|
// if (isRewarded)
|
|
// {
|
|
// //
|
|
// tests[i].reward = iReward;
|
|
// tests[i].rewardedAt = iRewardedAt;
|
|
// }
|
|
// }
|
|
|
|
//
|
|
// 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 //
|
|
// // );
|
|
// // }
|
|
// // }
|
|
|
|
// //
|
|
// bool hasFVG = iTest.fvg != NULL &&
|
|
// iTest.fvg.IsValid();
|
|
// if (hasFVG)
|
|
// {
|
|
// //
|
|
// XCBaseObject *fvgObj;
|
|
// bool isCreate = drawer.CreateFairValueGap(
|
|
// iTest.fvg,
|
|
// fvgObj //
|
|
// );
|
|
// if (isCreate)
|
|
// {
|
|
// //
|
|
// Add(
|
|
// fvgObj,
|
|
// drawnObjects //
|
|
// );
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
//
|
|
// END DRAW ...
|
|
//
|
|
|
|
//
|
|
Print("OBs Passed ...");
|
|
|
|
//
|
|
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
|
|
//
|
|
)
|
|
{
|
|
//
|
|
XCBaseObject *drawnObjects[];
|
|
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
Clean(tests);
|
|
|
|
//
|
|
datetime cTime = TimeCurrent();
|
|
|
|
//
|
|
XOBTest mTest;
|
|
mTest.symbol = ttfState.symbol;
|
|
mTest.period = ttfState.period;
|
|
|
|
//
|
|
// 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)
|
|
{
|
|
//
|
|
mTest.Clean();
|
|
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(),
|
|
iBreakerBar.period,
|
|
i //
|
|
);
|
|
if (!isInited)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
isValid = iBar.low > iOB.Upper();
|
|
if (!isValid)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (!isValid)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Bullish Order Blocks must Appear on Below on Last OB ...
|
|
XCOrderBlock *lastOB = NULL;
|
|
breakedBullOBsCount = ArraySize(breakedBullOBs);
|
|
bool hasLastOB = IsValidSize(breakedBullOBsCount);
|
|
if (hasLastOB)
|
|
{
|
|
lastOB = breakedBullOBs[breakedBullOBsCount - 1];
|
|
}
|
|
bool isLastOBPassed =
|
|
!hasLastOB
|
|
? true
|
|
: IsBelow(
|
|
iOB,
|
|
lastOB //
|
|
);
|
|
if (!isLastOBPassed)
|
|
{
|
|
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;
|
|
}
|
|
|
|
//
|
|
// Detect Related FVG ...
|
|
|
|
//
|
|
XCFVG *iFVG = NULL;
|
|
bool hasFVG = false;
|
|
bool hasFVGs = mtfState.HasBullishFairValueGaps();
|
|
int fvgsCount = mtfState.CountBullishFairValueGaps();
|
|
if (hasFVGs)
|
|
{
|
|
//
|
|
for (int j = 0; j < fvgsCount; j++)
|
|
{
|
|
//
|
|
XCFVG *jFVG = mtfState.bullishFairValueGaps[j];
|
|
|
|
//
|
|
// Detect FVG From date ...
|
|
bool isFromPassed = jFVG.From() > iOB.From();
|
|
if (!isFromPassed)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Fair Value Gaps Must be inside or Above that OB ...
|
|
bool isAbove = IsAboveDiff(
|
|
jFVG,
|
|
iOB,
|
|
true // Ignore Inside ...
|
|
);
|
|
bool isInside = IsInsideDiff(
|
|
jFVG,
|
|
iOB //
|
|
);
|
|
bool isPricePassed = isInside ||
|
|
isAbove;
|
|
if (!isPricePassed)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Liquidity Sweep Before FVG ...
|
|
bool isLiquiditySweeped = false;
|
|
|
|
if (!isLiquiditySweeped) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Set Nearest Valid FVG to OB From ...
|
|
bool canSetFVG =
|
|
!hasFVG
|
|
? true
|
|
: iFVG.From() > jFVG.From();
|
|
|
|
//
|
|
if (canSetFVG)
|
|
{
|
|
//
|
|
iFVG = jFVG;
|
|
hasFVG = iFVG != NULL &&
|
|
iFVG.IsValid();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (!hasFVG)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
XCBaseObject *iOBObj;
|
|
XCBaseObject *iFVGObj;
|
|
bool isOBCreated = drawer.CreateOrderBlock(
|
|
iOB,
|
|
iOBObj //
|
|
);
|
|
bool isFVGCreated = drawer.CreateFairValueGap(
|
|
iFVG,
|
|
iFVGObj //
|
|
);
|
|
|
|
//
|
|
Add(
|
|
iOB,
|
|
breakedBullOBs //
|
|
);
|
|
|
|
//
|
|
}
|
|
}
|
|
|
|
//
|
|
breakedBullOBsCount = ArraySize(breakedBullOBs);
|
|
hasBreakedBullOBs = IsValidSize(breakedBullOBsCount);
|
|
}
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
bool TestFVG(
|
|
XCFVG *fvg,
|
|
double &reward,
|
|
datetime &rewardedAt,
|
|
//
|
|
XCPOIDrawer *drawer,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
reward = 0;
|
|
rewardedAt = NULL;
|
|
|
|
//
|
|
result = fvg != NULL &&
|
|
fvg.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = fvg.GetPeriod();
|
|
}
|
|
|
|
//
|
|
bool isBullish = fvg.IsBullish();
|
|
ENUM_X_DIRECTION forDir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
XOHCL endBar;
|
|
result = fvg.FillEndBar(endBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL startBar;
|
|
result = fvg.FillStartBar(startBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL activatedBar;
|
|
ENUM_X_DIRECTION activatedDir;
|
|
result = fvg.IsActivated(
|
|
forDir,
|
|
activatedBar,
|
|
activatedDir,
|
|
forPeriod //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL breakedBar;
|
|
ENUM_X_DIRECTION breakedDir;
|
|
result = fvg.IsBreaked(
|
|
forDir,
|
|
breakedBar,
|
|
breakedDir,
|
|
forPeriod //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL triggerBar;
|
|
result = breakedBar.GetNextBar(triggerBar);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int breakedIndex = breakedBar.Index();
|
|
int triggerIndex = triggerBar.Index();
|
|
|
|
//
|
|
XRR fvgRR;
|
|
|
|
//
|
|
string symbol = triggerBar.symbol;
|
|
ENUM_TIMEFRAMES period = triggerBar.period;
|
|
|
|
//
|
|
double points = GetPoints(symbol);
|
|
|
|
//
|
|
double sl =
|
|
isBullish
|
|
? fvg.Lower() - 10 * points
|
|
: fvg.Upper() + 10 * points;
|
|
double entry =
|
|
isBullish
|
|
? fvg.Upper()
|
|
: fvg.Lower();
|
|
ENUM_X_POSITION_TYPES type =
|
|
isBullish
|
|
? X_POSITION_TYPE_LONG
|
|
: X_POSITION_TYPE_SHORT;
|
|
result = fvgRR.Init(
|
|
symbol,
|
|
period,
|
|
sl,
|
|
entry,
|
|
type //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
fvgRR.time = breakedBar.time;
|
|
|
|
//
|
|
XCRRObject *iObj;
|
|
result = drawer.CreateRR(
|
|
fvgRR,
|
|
iObj //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
Print("RR Created ...");
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
XCBaseObject *iChildObj;
|
|
CChartObjectVLine *iStartVLine;
|
|
CChartObjectVLine *iBreakVLine;
|
|
|
|
//
|
|
string iStartName = "Start_" + iChild.GetTag();
|
|
string iBreakName = "Break_" + iChild.GetTag();
|
|
ulong chartID = drawer.ChartIdentification();
|
|
int subWindow = drawer.SubWindowIdentification();
|
|
|
|
//
|
|
iStartVLine = new CChartObjectVLine();
|
|
bool isCreated = iStartVLine.Create(
|
|
chartID,
|
|
iStartName,
|
|
subWindow,
|
|
iChildStartedBar.time //
|
|
);
|
|
|
|
//
|
|
datetime iChildStartedBarToTime = iChildStartedBar.time + (PeriodSeconds(iChildStartedBar.period));
|
|
XCOHCLObject *iBarObj;
|
|
isCreated = drawer.CreateBar(
|
|
iChildStartedBar,
|
|
iBarObj,
|
|
iChildStartedBarToTime //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
//
|
|
iBarObj.BodyColor(clrYellow);
|
|
iBarObj.HighShadowColor(clrYellow);
|
|
iBarObj.LowShadowColor(clrYellow);
|
|
}
|
|
|
|
//
|
|
isCreated = drawer.CreateOrderBlock(
|
|
iChild,
|
|
iChildObj //
|
|
);
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
else if (isPriceInsideSupplyZone)
|
|
{
|
|
//
|
|
if (isPriceInsideVisionSupplyZone)
|
|
{
|
|
//
|
|
upper = conditions.visionHighestSupplyZone.Upper();
|
|
lower = conditions.visionHighestSupplyZone.Lower();
|
|
|
|
//
|
|
isInsideZoneDirectionBullish = false;
|
|
isInsideZoneDirectionBearish = true;
|
|
}
|
|
else if (isPriceInsideConsolidationSupplyZone)
|
|
{
|
|
//
|
|
upper = conditions.consolidationHighestSupplyZone.Upper();
|
|
lower = conditions.consolidationHighestSupplyZone.Lower();
|
|
|
|
//
|
|
isInsideZoneDirectionBullish = false;
|
|
isInsideZoneDirectionBearish = true;
|
|
}
|
|
}
|
|
else if (isPriceInsideDemandZone)
|
|
{
|
|
//
|
|
if (isPriceInsideVisionDemandZone)
|
|
{
|
|
//
|
|
upper = conditions.visionLowestDemandZone.Upper();
|
|
lower = conditions.visionLowestDemandZone.Lower();
|
|
|
|
//
|
|
isInsideZoneDirectionBullish = true;
|
|
isInsideZoneDirectionBearish = false;
|
|
}
|
|
else if (isPriceInsideConsolidationDemandZone)
|
|
{
|
|
//
|
|
upper = conditions.consolidationLowestDemandZone.Upper();
|
|
lower = conditions.consolidationLowestDemandZone.Lower();
|
|
|
|
//
|
|
isInsideZoneDirectionBullish = true;
|
|
isInsideZoneDirectionBearish = false;
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
// //
|
|
// bool isPriceAboveUpper =
|
|
// //
|
|
// decisionZBar.high < conditions.workingZone.zoneUpper &&
|
|
// decisionCBar.high < conditions.workingZone.zoneUpper &&
|
|
// //
|
|
// decisionZBar.low > conditions.workingZone.upper &&
|
|
// decisionCBar.low > conditions.workingZone.upper
|
|
// //
|
|
// ;
|
|
// if (isPriceAboveUpper)
|
|
// {
|
|
// //
|
|
// bullishPriority = X121SMC_XSUPDEMOBS_PRIORITY_NONE;
|
|
// bearishPriority = X121SMC_XSUPDEMOBS_PRIORITY_HIGH;
|
|
// }
|
|
|
|
// //
|
|
// bool isPriceInQuarterOne =
|
|
// //
|
|
// decisionZBar.high < conditions.workingZone.upper &&
|
|
// decisionCBar.high < conditions.workingZone.upper &&
|
|
// //
|
|
// decisionZBar.low > conditions.workingZone.quarter1 &&
|
|
// decisionCBar.low > conditions.workingZone.quarter1
|
|
// //
|
|
// ;
|
|
// if (isPriceInQuarterOne)
|
|
// {
|
|
// //
|
|
// bullishPriority = X121SMC_XSUPDEMOBS_PRIORITY_NONE;
|
|
// bearishPriority = X121SMC_XSUPDEMOBS_PRIORITY_REGULAR;
|
|
// }
|
|
|
|
// //
|
|
// bool isPriceInQuarterTwo =
|
|
// //
|
|
// decisionZBar.high < conditions.workingZone.quarter1 &&
|
|
// decisionCBar.high < conditions.workingZone.quarter1 &&
|
|
// //
|
|
// decisionZBar.low > conditions.workingZone.quarter2 &&
|
|
// decisionCBar.low > conditions.workingZone.quarter2
|
|
// //
|
|
// ;
|
|
// if (isPriceInQuarterTwo)
|
|
// {
|
|
// //
|
|
// bullishPriority = X121SMC_XSUPDEMOBS_PRIORITY_NONE;
|
|
// bearishPriority = X121SMC_XSUPDEMOBS_PRIORITY_LOW;
|
|
// }
|
|
|
|
// //
|
|
// bool isPriceInQuarterThree =
|
|
// //
|
|
// decisionZBar.high < conditions.workingZone.quarter2 &&
|
|
// decisionCBar.high < conditions.workingZone.quarter2 &&
|
|
// //
|
|
// decisionZBar.low > conditions.workingZone.quarter3 &&
|
|
// decisionCBar.low > conditions.workingZone.quarter3
|
|
// //
|
|
// ;
|
|
// if (isPriceInQuarterThree)
|
|
// {
|
|
// //
|
|
// bullishPriority = X121SMC_XSUPDEMOBS_PRIORITY_LOW;
|
|
// bearishPriority = X121SMC_XSUPDEMOBS_PRIORITY_NONE;
|
|
// }
|
|
|
|
// //
|
|
// bool isPriceInQuarterFour =
|
|
// //
|
|
// decisionZBar.high < conditions.workingZone.quarter3 &&
|
|
// decisionCBar.high < conditions.workingZone.quarter3 &&
|
|
// //
|
|
// decisionZBar.low > conditions.workingZone.lower &&
|
|
// decisionCBar.low > conditions.workingZone.lower
|
|
// //
|
|
// ;
|
|
// if (isPriceInQuarterFour)
|
|
// {
|
|
// //
|
|
// bullishPriority = X121SMC_XSUPDEMOBS_PRIORITY_REGULAR;
|
|
// bearishPriority = X121SMC_XSUPDEMOBS_PRIORITY_NONE;
|
|
// }
|
|
|
|
// //
|
|
// bool isPriceBelowLower =
|
|
// //
|
|
// decisionZBar.high < conditions.workingZone.lower &&
|
|
// decisionCBar.high < conditions.workingZone.lower &&
|
|
// //
|
|
// decisionZBar.low > conditions.workingZone.zoneLower &&
|
|
// decisionCBar.low > conditions.workingZone.zoneLower
|
|
// //
|
|
// ;
|
|
// if (isPriceBelowLower)
|
|
// {
|
|
// //
|
|
// bullishPriority = X121SMC_XSUPDEMOBS_PRIORITY_HIGH;
|
|
// bearishPriority = X121SMC_XSUPDEMOBS_PRIORITY_NONE;
|
|
// }
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
//
|
|
// Close ...
|
|
if (!ignoreCloseOnTPNearGuard)
|
|
{
|
|
//
|
|
double tpCloseDiff = (15 * points);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = ownPositions[i];
|
|
|
|
//
|
|
// Position Must be In Profit ...
|
|
if (iPosition.profit <= 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isPricePassed = MathAbs(iPosition.tp - iPosition.price) <= tpCloseDiff;
|
|
if (!isPricePassed)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isLong = IsLong(iPosition.type);
|
|
|
|
//
|
|
bool iHasGuard =
|
|
//
|
|
isLong
|
|
? //
|
|
false
|
|
//
|
|
: //
|
|
false
|
|
//
|
|
;
|
|
if (iHasGuard)
|
|
{
|
|
//
|
|
X121SMCGuard iGuard;
|
|
|
|
//
|
|
iGuard.time = cTime;
|
|
iGuard.symbol = symbol;
|
|
iGuard.provider = provider;
|
|
iGuard.action = X_121_SMC_GUARD_ACTION_CLOSE;
|
|
|
|
//
|
|
iGuard.ticket = iPosition.ticket;
|
|
|
|
//
|
|
AddGuard(
|
|
iGuard,
|
|
guards //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (hasLongs)
|
|
{
|
|
//
|
|
if (!ignoreCloseLongsOnBearishTrendGuard)
|
|
{
|
|
//
|
|
bool hasGuard = false; // hasDecisionBearishTrend;
|
|
|
|
//
|
|
if (hasGuard)
|
|
{
|
|
//
|
|
for (int i = 0; i < longsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = ownLongPositions[i];
|
|
|
|
//
|
|
// Position must be in Draw Down ...
|
|
if (iPosition.profit > 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
X121SMCGuard iGuard;
|
|
|
|
//
|
|
iGuard.time = cTime;
|
|
iGuard.symbol = symbol;
|
|
iGuard.provider = provider;
|
|
iGuard.action = X_121_SMC_GUARD_ACTION_CLOSE;
|
|
|
|
//
|
|
iGuard.ticket = iPosition.ticket;
|
|
|
|
//
|
|
AddGuard(
|
|
iGuard,
|
|
guards //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (hasShorts)
|
|
{
|
|
//
|
|
if (!ignoreCloseShortsOnBullishTrendGuard)
|
|
{
|
|
//
|
|
bool hasGuard = false; // hasDecisionBullishTrend;
|
|
|
|
//
|
|
if (hasGuard)
|
|
{
|
|
//
|
|
for (int i = 0; i < shortsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = ownShortPositions[i];
|
|
|
|
//
|
|
// Position must be in Draw Down ...
|
|
if (iPosition.profit > 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
X121SMCGuard iGuard;
|
|
|
|
//
|
|
iGuard.time = cTime;
|
|
iGuard.symbol = symbol;
|
|
iGuard.provider = provider;
|
|
iGuard.action = X_121_SMC_GUARD_ACTION_CLOSE;
|
|
|
|
//
|
|
iGuard.ticket = iPosition.ticket;
|
|
|
|
//
|
|
AddGuard(
|
|
iGuard,
|
|
guards //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close All ...
|
|
|
|
//
|
|
// Close All Weekend ...
|
|
if (!ignoreCloseAllWeekendGuard)
|
|
{
|
|
//
|
|
MqlDateTime mDate;
|
|
bool hasDate = TimeCurrent(mDate);
|
|
if (hasDate)
|
|
{
|
|
//
|
|
ENUM_X_WEEK_DAYS dayOfWeek = GetDayOfWeek();
|
|
|
|
//
|
|
bool isWeekend = dayOfWeek == X_WEEK_DAY_FRIDAY;
|
|
if (isWeekend && mDate.hour == 23 && mDate.min == 30)
|
|
{
|
|
//
|
|
X121SMCGuard guard;
|
|
|
|
//
|
|
guard.time = cTime;
|
|
guard.symbol = symbol;
|
|
guard.provider = provider;
|
|
guard.action = X_121_SMC_GUARD_ACTION_CLOSE_ALL;
|
|
|
|
//
|
|
AddGuard(
|
|
guard,
|
|
guards //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close Longs ...
|
|
if (hasLongs)
|
|
{
|
|
//
|
|
bool hasGuard =
|
|
//
|
|
false
|
|
//
|
|
// hasAnalyseBearishTrend &&
|
|
// hasDecisionBearishTrend
|
|
//
|
|
;
|
|
|
|
//
|
|
if (hasGuard)
|
|
{
|
|
//
|
|
X121SMCGuard guard;
|
|
|
|
//
|
|
guard.time = cTime;
|
|
guard.symbol = symbol;
|
|
guard.provider = provider;
|
|
guard.action = X_121_SMC_GUARD_ACTION_CLOSE_LONGS;
|
|
|
|
//
|
|
AddGuard(
|
|
guard,
|
|
guards //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close Shorts ...
|
|
if (hasShorts)
|
|
{
|
|
//
|
|
bool hasGuard =
|
|
//
|
|
false
|
|
//
|
|
// hasAnalyseBullishTrend &&
|
|
// hasDecisionBullishTrend
|
|
//
|
|
;
|
|
|
|
//
|
|
if (hasGuard)
|
|
{
|
|
//
|
|
X121SMCGuard guard;
|
|
|
|
//
|
|
guard.time = cTime;
|
|
guard.symbol = symbol;
|
|
guard.provider = provider;
|
|
guard.action = X_121_SMC_GUARD_ACTION_CLOSE_SHORTS;
|
|
|
|
//
|
|
AddGuard(
|
|
guard,
|
|
guards //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Partial Close ...
|
|
|
|
//
|
|
if (!ignorePartialCloseOnTrendChangeGuard)
|
|
{
|
|
//
|
|
if (hasLongs)
|
|
{
|
|
//
|
|
bool hasGuard =
|
|
//
|
|
false
|
|
//
|
|
// hasTriggerBearishTrend ||
|
|
// !hasDecisionBullishTrend
|
|
//
|
|
;
|
|
|
|
//
|
|
if (hasGuard)
|
|
{
|
|
//
|
|
for (int i = 0; i < longsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = ownLongPositions[i];
|
|
|
|
//
|
|
X121SMCGuard iGuard;
|
|
|
|
//
|
|
iGuard.time = cTime;
|
|
iGuard.symbol = symbol;
|
|
iGuard.provider = provider;
|
|
iGuard.action = X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE;
|
|
|
|
//
|
|
iGuard.ticket = iPosition.ticket;
|
|
iGuard.volumeMultiplier = 0.5;
|
|
|
|
//
|
|
AddGuard(
|
|
iGuard,
|
|
guards //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (hasShorts)
|
|
{
|
|
//
|
|
bool hasGuard =
|
|
//
|
|
false
|
|
//
|
|
// hasTriggerBullishTrend ||
|
|
// !hasDecisionBearishTrend
|
|
//
|
|
;
|
|
|
|
//
|
|
if (hasGuard)
|
|
{
|
|
//
|
|
for (int i = 0; i < shortsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = ownShortPositions[i];
|
|
|
|
//
|
|
X121SMCGuard iGuard;
|
|
|
|
//
|
|
iGuard.time = cTime;
|
|
iGuard.symbol = symbol;
|
|
iGuard.provider = provider;
|
|
iGuard.action = X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE;
|
|
|
|
//
|
|
iGuard.ticket = iPosition.ticket;
|
|
iGuard.volumeMultiplier = 0.5;
|
|
|
|
//
|
|
AddGuard(
|
|
iGuard,
|
|
guards //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Trail Stop ...
|
|
if (!ignoreTrailStopGuard)
|
|
{
|
|
//
|
|
if (hasLongs)
|
|
{
|
|
//
|
|
bool hasTrendGuard = false; // hasDecisionBearishTrend;
|
|
|
|
//
|
|
bool hasConsolidationGuard =
|
|
(hasConsolidationZone &&
|
|
isConsolidationZoneBreaked &&
|
|
isConsolidationZoneBreakedUp);
|
|
|
|
//
|
|
bool hasDecisionPriceZoneGuard =
|
|
false;
|
|
// (hasDecisionPriceZone &&
|
|
// isDecisionPriceZoneBullish &&
|
|
// isDecisionPriceZoneValidForVale &&
|
|
// isDecisionPriceZoneUpperBreakedUp);
|
|
|
|
//
|
|
bool hasAnalysePriceZoneGuard =
|
|
false;
|
|
// (hasAnalysePriceZone &&
|
|
// isAnalysePriceZoneBullish &&
|
|
// isAnalysePriceZoneValidForVale &&
|
|
// isAnalysePriceZoneUpperBreakedUp);
|
|
|
|
//
|
|
bool hasVerificationPriceZoneGuard =
|
|
false;
|
|
// (hasVerificationPriceZone &&
|
|
// isVerificationPriceZoneBullish &&
|
|
// isVerificationPriceZoneValidForVale &&
|
|
// isVerificationPriceZoneUpperBreakedUp);
|
|
|
|
//
|
|
bool hasGuard =
|
|
//
|
|
hasTrendGuard ||
|
|
hasConsolidationGuard ||
|
|
hasDecisionPriceZoneGuard ||
|
|
hasAnalysePriceZoneGuard ||
|
|
hasVerificationPriceZoneGuard
|
|
//
|
|
;
|
|
|
|
//
|
|
double guardStop =
|
|
hasConsolidationGuard
|
|
? consolidationZoneLower
|
|
: hasDecisionPriceZoneGuard
|
|
? 0 // decisionPriceZoneLower
|
|
: hasAnalysePriceZoneGuard
|
|
? 0 // analysePriceZoneLower
|
|
: hasVerificationPriceZoneGuard
|
|
? 0 // verificationPriceZoneLower
|
|
: 0;
|
|
|
|
//
|
|
if (hasGuard)
|
|
{
|
|
//
|
|
for (int i = 0; i < longsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = ownLongPositions[i];
|
|
|
|
//
|
|
// Position Must Be In Profit ...
|
|
if (iPosition.profit <= 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (hasTrendGuard)
|
|
{
|
|
// guardStop = decisionXConditions.strBuffer[1] - decisionXConditions.atrBuffer[1];
|
|
}
|
|
|
|
//
|
|
// Price Must Greater than Zone Lower ...
|
|
if (iPosition.price < guardStop)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Position Entry Must Lesser than Zone Lower ...
|
|
if (iPosition.entry > guardStop)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Position SL must be Zero or Lesser than Zone Lower ...
|
|
if (iPosition.sl != 0 &&
|
|
iPosition.sl > guardStop)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
X121SMCGuard iGuard;
|
|
|
|
//
|
|
iGuard.time = cTime;
|
|
iGuard.symbol = symbol;
|
|
iGuard.provider = provider;
|
|
iGuard.action = X_121_SMC_GUARD_ACTION_TRAIL_STOP;
|
|
|
|
//
|
|
iGuard.sl = guardStop;
|
|
iGuard.ticket = iPosition.ticket;
|
|
|
|
//
|
|
AddGuard(
|
|
iGuard,
|
|
guards //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (hasShorts)
|
|
{
|
|
//
|
|
bool hasTrendGuard = false; // hasDecisionBullishTrend;
|
|
|
|
//
|
|
bool hasConsolidationGuard =
|
|
(hasConsolidationZone &&
|
|
isConsolidationZoneBreaked &&
|
|
isConsolidationZoneBreakedDown);
|
|
|
|
//
|
|
bool hasDecisionPriceZoneGuard =
|
|
false;
|
|
// (hasDecisionPriceZone &&
|
|
// isDecisionPriceZoneBearish &&
|
|
// isDecisionPriceZoneValidForPeak &&
|
|
// isDecisionPriceZoneLowerBreakedDown);
|
|
|
|
//
|
|
bool hasAnalysePriceZoneGuard =
|
|
false;
|
|
// (hasAnalysePriceZone &&
|
|
// isAnalysePriceZoneBearish &&
|
|
// isAnalysePriceZoneValidForPeak &&
|
|
// isAnalysePriceZoneLowerBreakedDown);
|
|
|
|
//
|
|
bool hasVerificationPriceZoneGuard =
|
|
false;
|
|
// (hasVerificationPriceZone &&
|
|
// isVerificationPriceZoneBearish &&
|
|
// isVerificationPriceZoneValidForPeak &&
|
|
// isVerificationPriceZoneLowerBreakedDown);
|
|
|
|
//
|
|
bool hasGuard =
|
|
//
|
|
hasTrendGuard ||
|
|
hasConsolidationGuard ||
|
|
hasDecisionPriceZoneGuard ||
|
|
hasAnalysePriceZoneGuard ||
|
|
hasVerificationPriceZoneGuard
|
|
//
|
|
;
|
|
|
|
//
|
|
double guardStop =
|
|
hasConsolidationGuard
|
|
? consolidationZoneUpper
|
|
: hasDecisionPriceZoneGuard
|
|
? 0 // decisionPriceZoneUpper
|
|
: hasAnalysePriceZoneGuard
|
|
? 0 // analysePriceZoneUpper
|
|
: hasVerificationPriceZoneGuard
|
|
? 0 // verificationPriceZoneUpper
|
|
: 0;
|
|
|
|
//
|
|
if (hasGuard)
|
|
{
|
|
//
|
|
for (int i = 0; i < shortsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = ownShortPositions[i];
|
|
|
|
//
|
|
// Position Must Be In Profit ...
|
|
if (iPosition.profit <= 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
if (hasTrendGuard)
|
|
{
|
|
// guardStop = decisionXConditions.strBuffer[1] + decisionXConditions.atrBuffer[1];
|
|
}
|
|
|
|
//
|
|
// Price Must Lesser than Zone Upper ...
|
|
if (iPosition.price > guardStop)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Position Entry Must Greater than Zone Upper ...
|
|
if (iPosition.entry < guardStop)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Position SL must be Zero or Greater than Zone Upper ...
|
|
if (iPosition.sl != 0 &&
|
|
iPosition.sl < guardStop)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
X121SMCGuard iGuard;
|
|
|
|
//
|
|
iGuard.time = cTime;
|
|
iGuard.symbol = symbol;
|
|
iGuard.provider = provider;
|
|
iGuard.action = X_121_SMC_GUARD_ACTION_TRAIL_STOP;
|
|
|
|
//
|
|
iGuard.sl = guardStop;
|
|
iGuard.ticket = iPosition.ticket;
|
|
|
|
//
|
|
AddGuard(
|
|
iGuard,
|
|
guards //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Trail Target ...
|
|
if (!ignoreTrailTargetGuard)
|
|
{
|
|
//
|
|
if (hasLongs)
|
|
{
|
|
//
|
|
bool hasAnalyseGuard =
|
|
//
|
|
false
|
|
//
|
|
// (hasAnalysePriceZone &&
|
|
// isAnalysePriceZoneValidForPeak &&
|
|
// isAnalysePriceZoneUpperRejected)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool hasVerificationGuard =
|
|
//
|
|
false
|
|
//
|
|
// (hasVerificationPriceZone &&
|
|
// isVerificationPriceZoneValidForPeak &&
|
|
// isVerificationPriceZoneUpperRejected)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool hasGuard =
|
|
//
|
|
hasAnalyseGuard ||
|
|
hasVerificationGuard
|
|
//
|
|
;
|
|
|
|
//
|
|
double guardTP =
|
|
hasAnalyseGuard
|
|
? 0 // analysePriceZoneUpper
|
|
: hasVerificationGuard
|
|
? 0 // verificationPriceZoneUpper
|
|
: 0;
|
|
|
|
//
|
|
if (hasGuard)
|
|
{
|
|
//
|
|
for (int i = 0; i < longsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = ownLongPositions[i];
|
|
|
|
//
|
|
// Position Must Be In Profit ...
|
|
if (iPosition.profit <= 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
X121SMCGuard iGuard;
|
|
|
|
//
|
|
iGuard.time = cTime;
|
|
iGuard.symbol = symbol;
|
|
iGuard.provider = provider;
|
|
iGuard.action = X_121_SMC_GUARD_ACTION_TRAIL_TARGET;
|
|
|
|
//
|
|
iGuard.tp = guardTP;
|
|
iGuard.ticket = iPosition.ticket;
|
|
|
|
//
|
|
AddGuard(
|
|
iGuard,
|
|
guards //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (hasShorts)
|
|
{
|
|
//
|
|
bool hasAnalyseGuard =
|
|
//
|
|
false
|
|
//
|
|
// (hasAnalysePriceZone &&
|
|
// isAnalysePriceZoneValidForVale &&
|
|
// isAnalysePriceZoneLowerRejected)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool hasVerificationGuard =
|
|
//
|
|
false
|
|
//
|
|
// (hasVerificationPriceZone &&
|
|
// isVerificationPriceZoneValidForVale &&
|
|
// isVerificationPriceZoneLowerRejected)
|
|
//
|
|
;
|
|
|
|
//
|
|
bool hasGuard =
|
|
//
|
|
hasAnalyseGuard ||
|
|
hasVerificationGuard
|
|
//
|
|
;
|
|
|
|
//
|
|
double guardTP =
|
|
hasAnalyseGuard
|
|
? 0 // analysePriceZoneLower
|
|
: hasVerificationGuard
|
|
? 0 // verificationPriceZoneLower
|
|
: 0;
|
|
|
|
//
|
|
if (hasGuard)
|
|
{
|
|
//
|
|
for (int i = 0; i < shortsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = ownShortPositions[i];
|
|
|
|
//
|
|
// Position Must Be In Profit ...
|
|
if (iPosition.profit <= 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
X121SMCGuard iGuard;
|
|
|
|
//
|
|
iGuard.time = cTime;
|
|
iGuard.symbol = symbol;
|
|
iGuard.provider = provider;
|
|
iGuard.action = X_121_SMC_GUARD_ACTION_TRAIL_TARGET;
|
|
|
|
//
|
|
iGuard.tp = guardTP;
|
|
iGuard.ticket = iPosition.ticket;
|
|
|
|
//
|
|
AddGuard(
|
|
iGuard,
|
|
guards //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Hedge ...
|
|
if (!ignoreHedgeGuard)
|
|
{
|
|
}
|
|
|
|
///////////////////////////////////////////////////////// |