2366 lines
137 KiB
Plaintext
2366 lines
137 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Class Library
|
|
// --------------------------------------
|
|
// Name: XCX121SMCTestStrategy
|
|
// Description: provides all based classes for use ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://www.saherelm.ir"
|
|
#property version "1.00"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
|
|
//
|
|
#include "../../Helpers/x-saherelm.xchvwap.helper.mq5"
|
|
#include "../Classes/x-121.smc.base.strategy.class.mq5"
|
|
|
|
//
|
|
// Helper(s) ...
|
|
|
|
//
|
|
// XStrategy Class Implementation(s) ...
|
|
class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy
|
|
{
|
|
//
|
|
// Public ...
|
|
public:
|
|
//
|
|
|
|
//
|
|
// Constructor(s) ...
|
|
void XCX121SMCTestStrategy(
|
|
//
|
|
// Base ...
|
|
string _symbol, // Trading Symbol
|
|
ENUM_TIMEFRAMES _period // Trading TimeFrame
|
|
)
|
|
: XCX121SMCBaseStrategy(_symbol, _period)
|
|
{
|
|
InitialHelpers();
|
|
}
|
|
|
|
//
|
|
// Overrides Actions ...
|
|
|
|
//
|
|
// Check Conditions For Signal ...
|
|
bool HasSignal(
|
|
XSignal &signal,
|
|
X121SMCStrategyConditions &conditions //
|
|
) override
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
signal.Clean();
|
|
conditions.Clean();
|
|
|
|
//
|
|
int pushers = 0;
|
|
|
|
//
|
|
double sl = 0;
|
|
double tp = 0;
|
|
double risk = 0;
|
|
double entry = 0;
|
|
double reward = 0;
|
|
double r2r = R2R();
|
|
double volume = Volume();
|
|
ENUM_POSITION_TYPE type = POSITION_TYPE_BUY;
|
|
ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET;
|
|
|
|
//
|
|
bool hasLong = false;
|
|
bool hasShort = false;
|
|
|
|
//
|
|
// Start Calculations ...
|
|
|
|
//
|
|
string _symbol = GetSymbol();
|
|
ENUM_TIMEFRAMES _period = GetPeriod();
|
|
|
|
//
|
|
double points = GetPoints(_symbol);
|
|
|
|
//
|
|
int zIndex = 0;
|
|
int cIndex = zIndex + 1;
|
|
int pIndex = cIndex + 1;
|
|
int ppIndex = pIndex + 1;
|
|
|
|
//
|
|
// Retrieve Bars ...
|
|
|
|
//
|
|
// Zero Bar ...
|
|
XOHCL zBar;
|
|
result = zBar.Init(
|
|
_symbol,
|
|
_period,
|
|
zIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Last Bar ...
|
|
XOHCL cBar;
|
|
result = cBar.Init(
|
|
_symbol,
|
|
_period,
|
|
cIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Previous Bar ...
|
|
XOHCL pBar;
|
|
result = pBar.Init(
|
|
_symbol,
|
|
_period,
|
|
pIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isSpreadPassed = IsSpreadPass();
|
|
result = isSpreadPassed;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Try to Implement SMC Based Conditions ...
|
|
|
|
//
|
|
// 1- First Step is Find a Supply and Demand Zone ...
|
|
// - [] this Zone must be Fresh ...
|
|
// - [] contains Engulfing ...
|
|
// - [] has Order Block ...
|
|
// - [] has FVG ...
|
|
bool isDetected = DetecConditions(conditions);
|
|
if (isDetected)
|
|
{
|
|
//
|
|
// Check Conditions for Removing Exists ...
|
|
RemoveConditionsIfExists(conditions);
|
|
|
|
//
|
|
// Add New Condition ...
|
|
AddRef(
|
|
conditions,
|
|
mConditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
conditions.Clean();
|
|
|
|
//
|
|
// Check Conditions for Signal ...
|
|
int conditionsCount = ArraySize(mConditions);
|
|
if (!IsValidSize(conditionsCount))
|
|
{
|
|
//
|
|
result = false;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Remove Invalid Conditions ...
|
|
X121SMCStrategyConditions tmpConditions[];
|
|
Copy(
|
|
mConditions,
|
|
tmpConditions //
|
|
);
|
|
for (int i = 0; i < conditionsCount; i++)
|
|
{
|
|
//
|
|
X121SMCStrategyConditions iConditions = tmpConditions[i];
|
|
|
|
//
|
|
// Check Demand ...
|
|
if (iConditions.ValidateDemand())
|
|
{
|
|
//
|
|
// Check Bars ...
|
|
bool isInValid =
|
|
pBar.high < iConditions.demandZone.lower &&
|
|
cBar.high < iConditions.demandZone.lower &&
|
|
zBar.high < iConditions.demandZone.lower;
|
|
|
|
//
|
|
if (isInValid)
|
|
{
|
|
iConditions.CleanDemand();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Supply ...
|
|
if (iConditions.ValidateSupply())
|
|
{
|
|
//
|
|
// Check Bars ...
|
|
bool isInValid =
|
|
pBar.low > iConditions.demandZone.upper &&
|
|
cBar.low > iConditions.demandZone.upper &&
|
|
zBar.low > iConditions.demandZone.upper;
|
|
|
|
//
|
|
if (isInValid)
|
|
{
|
|
iConditions.CleanSupply();
|
|
}
|
|
}
|
|
|
|
//
|
|
bool isInValid = !iConditions.ValidateDemand() &&
|
|
iConditions.ValidateSupply();
|
|
if (isInValid)
|
|
{
|
|
//
|
|
ArrayRemove(
|
|
mConditions,
|
|
i,
|
|
1 //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(tmpConditions);
|
|
conditionsCount = ArraySize(mConditions);
|
|
if (!IsValidSize(conditionsCount))
|
|
{
|
|
//
|
|
result = false;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop through Conditions for Filter Based on POIs ...
|
|
int conditionsIDX = -1;
|
|
for (int i = 0; i < conditionsCount; i++)
|
|
{
|
|
//
|
|
result = false;
|
|
hasLong = false;
|
|
hasShort = false;
|
|
X121SMCStrategyConditions iConditions = mConditions[i];
|
|
|
|
//
|
|
X121SMCMarketStructure structure;
|
|
DetectMarketStructure(
|
|
structure,
|
|
iConditions //
|
|
);
|
|
|
|
//
|
|
bool isAllowLong = AllowLong();
|
|
bool isAllowShort = AllowShort();
|
|
result = isAllowLong || isAllowShort;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
bool hasValidDemand = iConditions.ValidateDemand();
|
|
bool hasValidSupply = iConditions.ValidateSupply();
|
|
result = hasValidDemand || hasValidSupply;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Reading Indicator's Conditions ...
|
|
XCHVWAPConditions chvwapConditions;
|
|
chvwapHelper.GetConditions(
|
|
chvwapConditions,
|
|
cIndex //
|
|
);
|
|
|
|
//
|
|
double selectedDemandUpper = MathMax(
|
|
iConditions.bullishOrderBlock.upper,
|
|
iConditions.bullishFVG.upper);
|
|
double selectedDemandLower = MathMax(
|
|
iConditions.bullishOrderBlock.lower,
|
|
iConditions.bullishFVG.lower);
|
|
|
|
//
|
|
double selectedSupplyUpper = MathMax(
|
|
iConditions.bearishOrderBlock.upper,
|
|
iConditions.bearishFVG.upper);
|
|
double selectedSupplyLower = MathMax(
|
|
iConditions.bearishOrderBlock.lower,
|
|
iConditions.bearishFVG.lower);
|
|
|
|
//
|
|
bool isPriceInsideDemandZone =
|
|
hasValidDemand &&
|
|
pBar.high < selectedDemandUpper &&
|
|
(pBar.low > selectedDemandLower ||
|
|
cBar.low > selectedDemandLower);
|
|
bool isPriceInsideSupplyZone =
|
|
hasValidSupply &&
|
|
pBar.low > selectedSupplyLower &&
|
|
(pBar.high < selectedSupplyUpper ||
|
|
cBar.high < selectedSupplyUpper);
|
|
|
|
//
|
|
bool isTicksBullish = IsTicksBullish();
|
|
bool isTicksBearish = IsTicksBearish();
|
|
bool isTicksHasMomentum = IsTicksHasMomentum();
|
|
|
|
//
|
|
double pricateChangeRate = 0.01;
|
|
double priceChange = GetPriceChanged(
|
|
GetSymbol(),
|
|
GetPeriod(),
|
|
0,
|
|
7 //
|
|
);
|
|
bool isBullishPriceChanged = priceChange >= pricateChangeRate;
|
|
bool isBearishPriceChanged = priceChange < 0 &&
|
|
MathAbs(priceChange) >= pricateChangeRate;
|
|
|
|
//
|
|
double _1Pip = GetPipPrice(iConditions.symbol);
|
|
|
|
//
|
|
// Longs ...
|
|
bool canCheckLong = isAllowLong &&
|
|
hasValidDemand &&
|
|
isTicksBullish &&
|
|
isTicksHasMomentum &&
|
|
isBullishPriceChanged &&
|
|
isPriceInsideDemandZone;
|
|
if (canCheckLong)
|
|
{
|
|
//
|
|
hasLong = false;
|
|
type = POSITION_TYPE_BUY;
|
|
entry = GetEntry(_symbol, type);
|
|
|
|
//
|
|
double slCandidates[];
|
|
int slCandidatesCount = DetectSLCandidates(
|
|
slCandidates,
|
|
entry,
|
|
iConditions,
|
|
X_POSITION_TYPE_LONG //
|
|
);
|
|
|
|
//
|
|
// Find Good Entry ...
|
|
hasLong = slCandidatesCount >= 3;
|
|
|
|
//
|
|
if (hasLong)
|
|
{
|
|
//
|
|
pushers = slCandidatesCount;
|
|
double selectedSL = GetMin(slCandidates);
|
|
sl = selectedSL - (5 * _1Pip);
|
|
risk = entry - sl;
|
|
reward = risk * r2r;
|
|
tp = entry + reward;
|
|
|
|
//
|
|
conditionsIDX = i;
|
|
conditions = mConditions[i];
|
|
mConditions[i].CleanDemand();
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Shorts ...
|
|
bool canCheckShort = isAllowShort &&
|
|
hasValidSupply &&
|
|
isTicksBearish &&
|
|
isTicksHasMomentum &&
|
|
isBearishPriceChanged &&
|
|
isPriceInsideSupplyZone;
|
|
if (canCheckShort)
|
|
{
|
|
//
|
|
hasShort = false;
|
|
type = POSITION_TYPE_SELL;
|
|
entry = GetEntry(_symbol, type);
|
|
|
|
//
|
|
double slCandidates[];
|
|
int slCandidatesCount = DetectSLCandidates(
|
|
slCandidates,
|
|
entry,
|
|
iConditions,
|
|
X_POSITION_TYPE_SHORT //
|
|
);
|
|
|
|
//
|
|
// Find Good Entry ...
|
|
hasShort = slCandidatesCount >= 3;
|
|
|
|
//
|
|
if (hasShort)
|
|
{
|
|
//
|
|
pushers = slCandidatesCount;
|
|
double selectedSL = GetMin(slCandidates);
|
|
sl = selectedSL + (5 * _1Pip);
|
|
risk = sl - entry;
|
|
reward = risk * r2r;
|
|
tp = entry - reward;
|
|
|
|
//
|
|
conditionsIDX = i;
|
|
conditions = mConditions[i];
|
|
mConditions[i].CleanSupply();
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = hasLong ||
|
|
hasShort;
|
|
|
|
//
|
|
// Rmove Signal Condition ...
|
|
if (result)
|
|
{
|
|
//
|
|
signal.sl = sl;
|
|
signal.tp = tp;
|
|
signal.type = type;
|
|
signal.mode = mode;
|
|
signal.entry = entry;
|
|
signal.volume = volume;
|
|
signal.symbol = _symbol;
|
|
signal.pushers = pushers;
|
|
signal.provider = GetTag();
|
|
signal.time = TimeCurrent();
|
|
signal.period = _5MState.period;
|
|
|
|
//
|
|
result = PrepareSignal(signal);
|
|
|
|
//
|
|
hasLong = false;
|
|
hasShort = false;
|
|
|
|
//
|
|
if (IsValidIndex(conditionsIDX))
|
|
{
|
|
//
|
|
ArrayRemove(
|
|
mConditions,
|
|
conditionsIDX,
|
|
1 //
|
|
);
|
|
}
|
|
|
|
//
|
|
DrawConditions(conditions);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Valid Market Conditions ...
|
|
*
|
|
* @param conditions: X121SMCStrategyConditions instance ...
|
|
*/
|
|
bool DetecConditions(X121SMCStrategyConditions &conditions) override
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Prepare Conditions ...
|
|
|
|
//
|
|
datetime time = TimeCurrent();
|
|
|
|
//
|
|
conditions.Clean();
|
|
conditions.time = time;
|
|
conditions.symbol = GetSymbol();
|
|
conditions.period = GetPeriod();
|
|
|
|
// //
|
|
// bool d1HasBullishTrend = HasBullishTrend(d1State);
|
|
// bool d1HasBearishTrend = HasBearishTrend(d1State);
|
|
|
|
// //
|
|
// bool h4HasBullishTrend = HasBullishTrend(h4State);
|
|
// bool h4HasBearishTrend = HasBearishTrend(h4State);
|
|
|
|
// //
|
|
// bool m15HasBullishTrend = HasBullishTrend(_15MState);
|
|
// bool m15HasBearishTrend = HasBearishTrend(_15MState);
|
|
|
|
// //
|
|
// bool m5HasBullishTrend = HasBullishTrend(m5State);
|
|
// bool m5HasBearishTrend = HasBearishTrend(m5State);
|
|
|
|
// //
|
|
// bool m1HasBullishTrend = HasBullishTrend(m1State);
|
|
// bool m1HasBearishTrend = HasBearishTrend(m1State);
|
|
|
|
// //
|
|
// bool isBullishTrendValid = h4HasBullishTrend &&
|
|
// m15HasBullishTrend &&
|
|
// m1HasBullishTrend;
|
|
// if (isBullishTrendValid)
|
|
// {
|
|
// Print("isBullishTrendValid");
|
|
// }
|
|
|
|
// //
|
|
// bool isBearishTrendValid = h4HasBearishTrend &&
|
|
// m15HasBearishTrend &&
|
|
// m1HasBearishTrend;
|
|
// if (isBearishTrendValid)
|
|
// {
|
|
// Print("isBearishTrendValid");
|
|
// }
|
|
|
|
//
|
|
int supplyZonesCount = ArraySize(_15MState.supplyZones);
|
|
int demandZonesCount = ArraySize(_15MState.demandZones);
|
|
result =
|
|
IsValidSize(demandZonesCount) ||
|
|
IsValidSize(supplyZonesCount);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool checkDemands = true;
|
|
bool checkSupplies = true;
|
|
|
|
//
|
|
// Demand Zone ...
|
|
if (checkDemands)
|
|
{
|
|
//
|
|
for (int i = 0; i < demandZonesCount; i++)
|
|
{
|
|
//
|
|
// Demand Zone ...
|
|
XZone iDemandZone = _15MState.demandZones[i];
|
|
iDemandZone.to = time;
|
|
conditions.demandZone = iDemandZone;
|
|
conditions.bullishOrderBlock.Clean();
|
|
conditions.bullishFVG.Clean();
|
|
|
|
//
|
|
// Bullish Order Block ...
|
|
int obCount = ArraySize(_15MState.bullishOrderBlocks);
|
|
if (IsValidSize(obCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < obCount; j++)
|
|
{
|
|
//
|
|
XZone jZone = _15MState.bullishOrderBlocks[j];
|
|
|
|
//
|
|
bool isBreaked = IsBreakeUpper(
|
|
jZone,
|
|
iDemandZone //
|
|
);
|
|
if (isBreaked)
|
|
{
|
|
//
|
|
jZone.to = time;
|
|
conditions.bullishOrderBlock = jZone;
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate Order Block ...
|
|
bool isValidOrderBlock = conditions.bullishOrderBlock.IsValid();
|
|
if (!isValidOrderBlock)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Bullish FVG ...
|
|
int fairValueGapsCount = ArraySize(_15MState.bullishFVGs);
|
|
if (IsValidSize(fairValueGapsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < fairValueGapsCount; j++)
|
|
{
|
|
//
|
|
XZone jZone = _15MState.bullishFVGs[j];
|
|
|
|
//
|
|
bool isBreaked = IsBreakeUpper(
|
|
jZone,
|
|
conditions.bullishOrderBlock //
|
|
);
|
|
if (isBreaked)
|
|
{
|
|
//
|
|
jZone.to = time;
|
|
conditions.bullishFVG = jZone;
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate FVG ...
|
|
bool isValidFVG = conditions.bullishFVG.IsValid();
|
|
if (!isValidFVG)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Detect Inside Demand POIs ...
|
|
|
|
//
|
|
// Order Blocks ...
|
|
// CState ...
|
|
int orderBlocksCount = ArraySize(_CombineState.bullishOrderBlocks);
|
|
if (IsValidSize(orderBlocksCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < orderBlocksCount; j++)
|
|
{
|
|
//
|
|
XZone jZone = _CombineState.bullishOrderBlocks[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jZone,
|
|
iDemandZone,
|
|
X_ZONE_LOWER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
jZone.to = TimeCurrent();
|
|
|
|
//
|
|
AddIfNotExists(
|
|
jZone,
|
|
conditions.bullishOrderBlocks //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support Zones ...
|
|
// CState ...
|
|
int supportsCount = ArraySize(_CombineState.supportZones);
|
|
if (IsValidSize(supportsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < supportsCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = _CombineState.supportZones[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jBar,
|
|
iDemandZone,
|
|
X_ZONE_LOWER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.supports //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
// CState ...
|
|
int fvgsCount = ArraySize(_CombineState.bullishFVGs);
|
|
if (IsValidSize(fvgsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < fvgsCount; j++)
|
|
{
|
|
//
|
|
XZone jFVG = _CombineState.bullishFVGs[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jFVG,
|
|
iDemandZone,
|
|
X_ZONE_LOWER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
jFVG.to = TimeCurrent();
|
|
|
|
//
|
|
AddIfNotExists(
|
|
jFVG,
|
|
conditions.bullishFVGs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swings ...
|
|
// CState ...
|
|
int swingsCount = ArraySize(_CombineState.swingLows);
|
|
if (IsValidSize(swingsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < swingsCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = _CombineState.swingLows[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jBar,
|
|
iDemandZone,
|
|
X_ZONE_LOWER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.swingLows //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Momentum Bars ...
|
|
// CState ...
|
|
int momentumBarsCount = ArraySize(_CombineState.momentumBars);
|
|
if (IsValidSize(momentumBarsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < momentumBarsCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = _CombineState.momentumBars[j];
|
|
|
|
//
|
|
bool isInside =
|
|
jBar.IsBullish() &&
|
|
jBar.time > iDemandZone.from &&
|
|
IsInside(
|
|
jBar,
|
|
iDemandZone,
|
|
X_ZONE_LOWER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.bullishMomentumBars //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Rejection Bars ...
|
|
// CState ...
|
|
int rejectionBarsCount = ArraySize(_CombineState.rejectionBars);
|
|
if (IsValidSize(rejectionBarsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < rejectionBarsCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = _CombineState.rejectionBars[j];
|
|
|
|
//
|
|
bool isInside =
|
|
jBar.GetLowShadow() > jBar.GetHighShadow() &&
|
|
jBar.time > iDemandZone.from &&
|
|
IsInside(
|
|
jBar,
|
|
iDemandZone,
|
|
X_ZONE_LOWER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.bullishRejectionBars //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
bool hasValidDemandZone = conditions.ValidateDemand();
|
|
if (!hasValidDemandZone)
|
|
{
|
|
conditions.CleanDemand();
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Supply Zone ...
|
|
if (checkSupplies)
|
|
{
|
|
//
|
|
for (int i = 0; i < supplyZonesCount; i++)
|
|
{
|
|
//
|
|
// Supply Zone ...
|
|
XZone iSupplyZone = _15MState.supplyZones[i];
|
|
iSupplyZone.to = time;
|
|
conditions.supplyZone = iSupplyZone;
|
|
conditions.bearishOrderBlock.Clean();
|
|
conditions.bearishFVG.Clean();
|
|
|
|
//
|
|
// Bearish Order Block ...
|
|
int obCount = ArraySize(_15MState.bearishOrderBlocks);
|
|
if (IsValidSize(obCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < obCount; j++)
|
|
{
|
|
//
|
|
XZone jZone = _15MState.bearishOrderBlocks[j];
|
|
|
|
//
|
|
bool isBreaked = IsBreakeLower(
|
|
jZone,
|
|
iSupplyZone //
|
|
);
|
|
if (isBreaked)
|
|
{
|
|
//
|
|
jZone.to = time;
|
|
conditions.bearishOrderBlock = jZone;
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate Order Block ...
|
|
bool isValidOrderBlock = conditions.bearishOrderBlock.IsValid();
|
|
if (!isValidOrderBlock)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Bearish FVG ...
|
|
int fairValueGapsCount = ArraySize(_15MState.bearishFVGs);
|
|
if (IsValidSize(fairValueGapsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < fairValueGapsCount; j++)
|
|
{
|
|
//
|
|
XZone jZone = _15MState.bearishFVGs[j];
|
|
|
|
//
|
|
bool isBreaked = IsBreakeLower(
|
|
jZone,
|
|
conditions.bearishOrderBlock //
|
|
);
|
|
if (isBreaked)
|
|
{
|
|
//
|
|
jZone.to = time;
|
|
conditions.bearishFVG = jZone;
|
|
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate FVG ...
|
|
bool isValidFVG = conditions.bearishFVG.IsValid();
|
|
if (!isValidFVG)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Detect Inside Demand POIs ...
|
|
|
|
//
|
|
// Order Blocks ...
|
|
// CState ...
|
|
int orderBlocksCount = ArraySize(_CombineState.bearishOrderBlocks);
|
|
if (IsValidSize(orderBlocksCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < orderBlocksCount; j++)
|
|
{
|
|
//
|
|
XZone jZone = _CombineState.bearishOrderBlocks[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jZone,
|
|
iSupplyZone,
|
|
X_ZONE_UPPER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
jZone.to = TimeCurrent();
|
|
|
|
//
|
|
AddIfNotExists(
|
|
jZone,
|
|
conditions.bearishOrderBlocks //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistance Zones ...
|
|
// CState ...
|
|
int resistancesCount = ArraySize(_CombineState.resistanceZones);
|
|
if (IsValidSize(resistancesCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < resistancesCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = _CombineState.resistanceZones[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jBar,
|
|
iSupplyZone,
|
|
X_ZONE_UPPER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.resistances //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
// CState ...
|
|
int fvgsCount = ArraySize(_CombineState.bearishFVGs);
|
|
if (IsValidSize(fvgsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < fvgsCount; j++)
|
|
{
|
|
//
|
|
XZone jFVG = _CombineState.bearishFVGs[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jFVG,
|
|
iSupplyZone,
|
|
X_ZONE_UPPER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
jFVG.to = TimeCurrent();
|
|
|
|
//
|
|
AddIfNotExists(
|
|
jFVG,
|
|
conditions.bearishFVGs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swings ...
|
|
// CState ...
|
|
int swingsCount = ArraySize(_CombineState.swingHighs);
|
|
if (IsValidSize(swingsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < swingsCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = _CombineState.swingHighs[j];
|
|
|
|
//
|
|
bool isInside = IsInside(
|
|
jBar,
|
|
iSupplyZone,
|
|
X_ZONE_UPPER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.swingHighs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Momentum Bars ...
|
|
// CState ...
|
|
int momentumBarsCount = ArraySize(_CombineState.momentumBars);
|
|
if (IsValidSize(momentumBarsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < momentumBarsCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = _CombineState.momentumBars[j];
|
|
|
|
//
|
|
bool isInside =
|
|
jBar.IsBearish() &&
|
|
jBar.time > iSupplyZone.from &&
|
|
IsInside(
|
|
jBar,
|
|
iSupplyZone,
|
|
X_ZONE_UPPER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.bearishMomentumBars //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Rejection Bars ...
|
|
// CState ...
|
|
int rejectionBarsCount = ArraySize(_CombineState.rejectionBars);
|
|
if (IsValidSize(rejectionBarsCount))
|
|
{
|
|
//
|
|
for (int j = 0; j < rejectionBarsCount; j++)
|
|
{
|
|
//
|
|
XOHCL jBar = _CombineState.rejectionBars[j];
|
|
|
|
//
|
|
bool isInside =
|
|
jBar.GetLowShadow() < jBar.GetHighShadow() &&
|
|
jBar.time > iSupplyZone.from &&
|
|
IsInside(
|
|
jBar,
|
|
iSupplyZone,
|
|
X_ZONE_UPPER_EDGE,
|
|
true //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
jBar,
|
|
conditions.bearishRejectionBars //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
bool hasValidSupplyZone = conditions.ValidateSupply();
|
|
if (!hasValidSupplyZone)
|
|
{
|
|
conditions.CleanSupply();
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand ...
|
|
// Used for Long ...
|
|
bool hasValidDemandZone = conditions.ValidateDemand();
|
|
|
|
//
|
|
// Supply ...
|
|
// Used for Short ...
|
|
bool hasValidSupplyZone = conditions.ValidateSupply();
|
|
|
|
//
|
|
// Check Conditions is Valid or not ...
|
|
result = hasValidDemandZone ||
|
|
hasValidSupplyZone;
|
|
if (!result)
|
|
{
|
|
conditions.Clean();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect Market Structure for Specified Conditions ...
|
|
*
|
|
* @param structure: X121SMCMarketStructure instance ...
|
|
* @param conditions: X121SMCStrategyConditions instance ...
|
|
* @param d1State: XPOIState instance ...
|
|
* @param h4State: XPOIState instance ...
|
|
* @param _15MState: XPOIState instance ...
|
|
* @param m5State: XPOIState instance ...
|
|
* @param m1State: XPOIState instance ...
|
|
*/
|
|
void DetectMarketStructure(
|
|
X121SMCMarketStructure &structure,
|
|
X121SMCStrategyConditions &conditions //
|
|
) override
|
|
{
|
|
//
|
|
structure.Clean();
|
|
|
|
//
|
|
if (!conditions.IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
bool hasValidDemand = conditions.ValidateDemand();
|
|
bool hasValidSupply = conditions.ValidateSupply();
|
|
if (!hasValidDemand && !hasValidSupply)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
structure.supplyZone = conditions.supplyZone;
|
|
structure.demandZone = conditions.demandZone;
|
|
|
|
//
|
|
datetime cTime = TimeCurrent();
|
|
|
|
//
|
|
// Supply Zones ...
|
|
int supplysCount = ArraySize(_CombineState.supplyZones);
|
|
if (IsValidSize(supplysCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < supplysCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = _CombineState.supplyZones[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iZone,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
iZone.to = cTime;
|
|
|
|
//
|
|
AddIfNotExists(
|
|
iZone,
|
|
structure.supplyZones //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Demand Zones ...
|
|
int demandsCount = ArraySize(_CombineState.demandZones);
|
|
if (IsValidSize(demandsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < demandsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = _CombineState.demandZones[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iZone,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
iZone.to = cTime;
|
|
|
|
//
|
|
AddIfNotExists(
|
|
iZone,
|
|
structure.demandZones //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Order Blocks ...
|
|
|
|
//
|
|
// Bullish OBs ...
|
|
int bullishOBsCount = ArraySize(_CombineState.bullishOrderBlocks);
|
|
if (IsValidSize(bullishOBsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < bullishOBsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = _CombineState.bullishOrderBlocks[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iZone,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
iZone.to = cTime;
|
|
|
|
//
|
|
AddIfNotExists(
|
|
iZone,
|
|
structure.bullishOrderBlocks //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish OBs ...
|
|
int bearishOBsCount = ArraySize(_CombineState.bearishOrderBlocks);
|
|
if (IsValidSize(bearishOBsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < bearishOBsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = _CombineState.bearishOrderBlocks[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iZone,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
iZone.to = cTime;
|
|
|
|
//
|
|
AddIfNotExists(
|
|
iZone,
|
|
structure.bearishOrderBlocks //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
|
|
//
|
|
// Bullish FVGs ...
|
|
int bullishFVGsCount = ArraySize(_CombineState.bullishFVGs);
|
|
if (IsValidSize(bullishFVGsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < bullishFVGsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = _CombineState.bullishFVGs[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iZone,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
iZone.to = cTime;
|
|
|
|
//
|
|
AddIfNotExists(
|
|
iZone,
|
|
structure.bullishFVGs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish FVGs ...
|
|
int bearishFVGsCount = ArraySize(_CombineState.bearishFVGs);
|
|
if (IsValidSize(bearishFVGsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < bearishFVGsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = _CombineState.bearishFVGs[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iZone,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
iZone.to = cTime;
|
|
|
|
//
|
|
AddIfNotExists(
|
|
iZone,
|
|
structure.bearishFVGs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swing Highs ...
|
|
int swingHighsCount = ArraySize(_CombineState.swingHighs);
|
|
if (IsValidSize(swingHighsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < swingHighsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = _CombineState.swingHighs[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iBar,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.swingHighs //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swing Lows ...
|
|
int swingLowsCount = ArraySize(_CombineState.swingLows);
|
|
if (IsValidSize(swingLowsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < swingLowsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = _CombineState.swingLows[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iBar,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.swingLows //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support Zones ...
|
|
int supportsCount = ArraySize(_CombineState.supportZones);
|
|
if (IsValidSize(supportsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < supportsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = _CombineState.supportZones[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iBar,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.supports //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistance Zones ...
|
|
int resistancesCount = ArraySize(_CombineState.resistanceZones);
|
|
if (IsValidSize(resistancesCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < resistancesCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = _CombineState.resistanceZones[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iBar,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.resistances //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Momentum Bars ...
|
|
int momentumBarCount = ArraySize(_CombineState.momentumBars);
|
|
if (IsValidSize(momentumBarCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < momentumBarCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = _CombineState.momentumBars[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iBar,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
bool isBullish = iBar.IsBullish();
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.bullishMomentumBars //
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.bearishMomentumBars //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Rejection Bars ...
|
|
int rejectionBarCount = ArraySize(_CombineState.rejectionBars);
|
|
if (IsValidSize(rejectionBarCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < rejectionBarCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = _CombineState.rejectionBars[i];
|
|
|
|
//
|
|
bool isBetween = IsBetween(
|
|
iBar,
|
|
structure.supplyZone,
|
|
structure.demandZone //
|
|
);
|
|
if (isBetween)
|
|
{
|
|
//
|
|
bool isBullish = iBar.GetLowShadow() > iBar.GetHighShadow();
|
|
|
|
//
|
|
if (isBullish)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.bullishRejectionBars //
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iBar,
|
|
structure.bearishRejectionBars //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove Specific Conditions if Exists ...
|
|
*
|
|
* @param conditions: X121SMCStrategyConditions instance ...
|
|
*/
|
|
void RemoveConditionsIfExists(X121SMCStrategyConditions &conditions) override
|
|
{
|
|
//
|
|
int count = ArraySize(mConditions);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
bool hasValidSupply = conditions.ValidateSupply();
|
|
bool hasValidDemand = conditions.ValidateDemand();
|
|
if (!hasValidSupply && !hasValidDemand)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
X121SMCStrategyConditions iConditions = mConditions[i];
|
|
|
|
//
|
|
bool isSupplySame =
|
|
hasValidSupply &&
|
|
iConditions.ValidateSupply() &&
|
|
conditions.supplyZone.from == iConditions.supplyZone.from &&
|
|
conditions.supplyZone.upper == iConditions.supplyZone.upper &&
|
|
conditions.supplyZone.lower == iConditions.supplyZone.lower;
|
|
bool isDemandSame =
|
|
hasValidDemand &&
|
|
iConditions.ValidateDemand() &&
|
|
conditions.demandZone.from == iConditions.demandZone.from &&
|
|
conditions.demandZone.upper == iConditions.demandZone.upper &&
|
|
conditions.demandZone.lower == iConditions.demandZone.lower;
|
|
|
|
//
|
|
if (isSupplySame || isDemandSame)
|
|
{
|
|
//
|
|
idx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
if (IsValidIndex(idx))
|
|
{
|
|
//
|
|
ArrayRemove(
|
|
mConditions,
|
|
idx,
|
|
1 //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Customize Strategy Identifier ...
|
|
string GetTag() override
|
|
{
|
|
return X121SMCSUPDEMStrategyToken;
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// XCHVWAP ...
|
|
XCHVWAPInputs chvwapInputs;
|
|
XSCXCHVWAPHelper *chvwapHelper;
|
|
|
|
//
|
|
// Private ...
|
|
private:
|
|
//
|
|
// Props ...
|
|
|
|
/**
|
|
* Validate a Condition ...
|
|
*
|
|
* @param conditions: Argument 1
|
|
* @return ( bool )
|
|
*/
|
|
bool ValidateConditions(X121SMCStrategyConditions &conditions)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = conditions.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool hasValidDemnd = conditions.ValidateDemand();
|
|
bool hasValidSupply = conditions.ValidateSupply();
|
|
result = hasValidDemnd || hasValidSupply;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string _symbol = GetSymbol();
|
|
ENUM_TIMEFRAMES _period = GetPeriod();
|
|
|
|
//
|
|
int zIndex = 0;
|
|
int cIndex = zIndex + 1;
|
|
int pIndex = cIndex + 1;
|
|
|
|
//
|
|
XOHCL zBar;
|
|
result = zBar.Init(
|
|
_symbol,
|
|
_period,
|
|
zIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL cBar;
|
|
result = cBar.Init(
|
|
_symbol,
|
|
_period,
|
|
cIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
hasValidDemnd
|
|
? cBar.high < conditions.demandZone.upper &&
|
|
zBar.high < conditions.demandZone.upper &&
|
|
cBar.low > conditions.demandZone.lower &&
|
|
zBar.low > conditions.demandZone.lower
|
|
: hasValidSupply
|
|
? cBar.high < conditions.demandZone.upper &&
|
|
zBar.high < conditions.demandZone.upper &&
|
|
cBar.low > conditions.demandZone.lower &&
|
|
zBar.low > conditions.demandZone.lower
|
|
: false;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Initial Required Indicators Helper ...
|
|
*/
|
|
void InitialHelpers()
|
|
{
|
|
//
|
|
// XCHVWAP ...
|
|
|
|
//
|
|
// Short ...
|
|
ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_MANUALLY; // How to Find Period
|
|
ENUM_TIMEFRAMES scPeriod = PERIOD_M15; // Time Period
|
|
|
|
//
|
|
// Medium ...
|
|
ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_MANUALLY; // How to Find Period
|
|
ENUM_TIMEFRAMES mcPeriod = PERIOD_H1; // Time Period
|
|
|
|
//
|
|
// Long ...
|
|
ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_MANUALLY; // How to Find Period
|
|
ENUM_TIMEFRAMES lcPeriod = PERIOD_H4; // Time Period
|
|
|
|
//
|
|
// Hind ...
|
|
ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_MANUALLY; // How to Find Period
|
|
ENUM_TIMEFRAMES hcPeriod = PERIOD_D1; // Time Period
|
|
|
|
//
|
|
chvwapInputs.Default();
|
|
|
|
//
|
|
chvwapInputs.scMethod = scMethod;
|
|
chvwapInputs.scPeriod = scPeriod;
|
|
chvwapInputs.mcMethod = mcMethod;
|
|
chvwapInputs.mcPeriod = mcPeriod;
|
|
chvwapInputs.lcMethod = lcMethod;
|
|
chvwapInputs.lcPeriod = lcPeriod;
|
|
chvwapInputs.hcMethod = hcMethod;
|
|
chvwapInputs.hcPeriod = hcPeriod;
|
|
|
|
//
|
|
chvwapInputs.showShort = true;
|
|
chvwapInputs.showMedium = true;
|
|
chvwapInputs.showLong = true;
|
|
chvwapInputs.showHind = true;
|
|
|
|
//
|
|
chvwapHelper = new XSCXCHVWAPHelper();
|
|
chvwapHelper.Init(
|
|
GetSymbol(),
|
|
GetPeriod(),
|
|
chvwapInputs //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Override Draw Condition ...
|
|
|
|
/**
|
|
* Draw Specific Condition ...
|
|
*
|
|
* @param conditions: X121SMCStrategyConditions instance ...
|
|
*/
|
|
void DrawConditions(
|
|
X121SMCStrategyConditions &conditions //
|
|
)
|
|
{
|
|
//
|
|
// Draw Configurations ...
|
|
|
|
//
|
|
bool drawMainDemand = true;
|
|
bool drawMainSupply = true;
|
|
|
|
//
|
|
bool drawMainBullishOrderBlock = true;
|
|
bool drawMainBearishOrderBlock = true;
|
|
|
|
//
|
|
bool drawMainBullishFVG = true;
|
|
bool drawMainBearishFVG = true;
|
|
|
|
//
|
|
bool drawOrderBlocks = false;
|
|
bool drawFVGs = false;
|
|
bool drawSupportResistances = false;
|
|
bool drawSwings = false;
|
|
bool drawMomentumBars = false;
|
|
bool drawRejectionBars = false;
|
|
|
|
//
|
|
bool renewDates = true;
|
|
|
|
//
|
|
if (!conditions.IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
datetime time = TimeCurrent();
|
|
bool hasValidDemand = conditions.ValidateDemand();
|
|
bool hasValidSupply = conditions.ValidateSupply();
|
|
if (!hasValidDemand && !hasValidSupply)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Demand Zone ...
|
|
if (hasValidDemand)
|
|
{
|
|
//
|
|
// Demand ...
|
|
if (drawMainDemand)
|
|
{
|
|
//
|
|
if (renewDates)
|
|
{
|
|
conditions.demandZone.to = time;
|
|
}
|
|
|
|
//
|
|
XCDemandZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateDemandZone(
|
|
conditions.demandZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
if (drawMainBullishOrderBlock)
|
|
{
|
|
//
|
|
if (renewDates)
|
|
{
|
|
conditions.bullishOrderBlock.to = time;
|
|
}
|
|
|
|
//
|
|
XCBullishOrderBlockObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishOrderBlock(
|
|
conditions.bullishOrderBlock,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
if (drawMainBullishFVG)
|
|
{
|
|
//
|
|
if (renewDates)
|
|
{
|
|
conditions.bullishFVG.to = time;
|
|
}
|
|
|
|
//
|
|
XCBullishFVGObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishFVG(
|
|
conditions.bullishFVG,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Order Blocks ...
|
|
int obsCount = ArraySize(conditions.bullishOrderBlocks);
|
|
if (drawOrderBlocks &&
|
|
IsValidSize(obsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < obsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = conditions.bullishOrderBlocks[i];
|
|
|
|
//
|
|
if (renewDates)
|
|
{
|
|
iZone.to = time;
|
|
}
|
|
|
|
//
|
|
XCBullishOrderBlockObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishOrderBlock(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
int fvgsCount = ArraySize(conditions.bullishFVGs);
|
|
if (drawFVGs &&
|
|
IsValidSize(fvgsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < fvgsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = conditions.bullishFVGs[i];
|
|
|
|
//
|
|
if (renewDates)
|
|
{
|
|
iZone.to = time;
|
|
}
|
|
|
|
//
|
|
XCBullishFVGObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishFVG(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Supports ...
|
|
int supportsCount = ArraySize(conditions.supports);
|
|
if (drawSupportResistances &&
|
|
IsValidSize(supportsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < supportsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.supports[i];
|
|
|
|
//
|
|
XCSupportZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSupportZone(
|
|
iBar,
|
|
iObj,
|
|
time //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swings ...
|
|
int swingsCount = ArraySize(conditions.swingLows);
|
|
if (drawSwings &&
|
|
IsValidSize(swingsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < swingsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.swingLows[i];
|
|
|
|
//
|
|
XCSwingLowObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSwingLow(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Momentum Bars ...
|
|
int momentumBarsCount = ArraySize(conditions.bullishMomentumBars);
|
|
if (drawMomentumBars &&
|
|
IsValidSize(momentumBarsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < momentumBarsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.bullishMomentumBars[i];
|
|
|
|
//
|
|
XCBullishMomentumBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishMomentumBar(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Rejection Bars ...
|
|
int rejectionBarsCount = ArraySize(conditions.bullishRejectionBars);
|
|
if (drawRejectionBars &&
|
|
IsValidSize(rejectionBarsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < rejectionBarsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.bullishRejectionBars[i];
|
|
|
|
//
|
|
XCBullishRejectionBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBullishRejectionBar(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Supply Zone ...
|
|
if (hasValidSupply)
|
|
{
|
|
//
|
|
// Supply ...
|
|
if (drawMainSupply)
|
|
{
|
|
//
|
|
if (renewDates)
|
|
{
|
|
conditions.supplyZone.to = time;
|
|
}
|
|
|
|
//
|
|
XCSupplyZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSupplyZone(
|
|
conditions.supplyZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
if (drawMainBearishOrderBlock)
|
|
{
|
|
//
|
|
if (renewDates)
|
|
{
|
|
conditions.bearishOrderBlock.to = time;
|
|
}
|
|
|
|
//
|
|
XCBearishOrderBlockObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishOrderBlock(
|
|
conditions.bearishOrderBlock,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
if (drawMainBearishFVG)
|
|
{
|
|
//
|
|
if (renewDates)
|
|
{
|
|
conditions.bearishFVG.to = time;
|
|
}
|
|
|
|
//
|
|
XCBearishFVGObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishFVG(
|
|
conditions.bearishFVG,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Order Blocks ...
|
|
int obsCount = ArraySize(conditions.bearishOrderBlocks);
|
|
if (drawOrderBlocks &&
|
|
IsValidSize(obsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < obsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = conditions.bearishOrderBlocks[i];
|
|
|
|
//
|
|
if (renewDates)
|
|
{
|
|
iZone.to = time;
|
|
}
|
|
|
|
//
|
|
XCBearishOrderBlockObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishOrderBlock(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fair Value Gaps ...
|
|
int fvgsCount = ArraySize(conditions.bearishFVGs);
|
|
if (drawFVGs &&
|
|
IsValidSize(fvgsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < fvgsCount; i++)
|
|
{
|
|
//
|
|
XZone iZone = conditions.bearishFVGs[i];
|
|
|
|
//
|
|
if (renewDates)
|
|
{
|
|
iZone.to = time;
|
|
}
|
|
|
|
//
|
|
XCBearishFVGObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishFVG(
|
|
iZone,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Resistances ...
|
|
int resistancesCount = ArraySize(conditions.resistances);
|
|
if (drawSupportResistances &&
|
|
IsValidSize(resistancesCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < resistancesCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.resistances[i];
|
|
|
|
//
|
|
XCResistanceZoneObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateResistanceZone(
|
|
iBar,
|
|
iObj,
|
|
time //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swings ...
|
|
int swingsCount = ArraySize(conditions.swingHighs);
|
|
if (drawSwings &&
|
|
IsValidSize(swingsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < swingsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.swingHighs[i];
|
|
|
|
//
|
|
XCSwingHighObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateSwingHigh(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Momentum Bars ...
|
|
int momentumBarsCount = ArraySize(conditions.bearishMomentumBars);
|
|
if (drawMomentumBars &&
|
|
IsValidSize(momentumBarsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < momentumBarsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.bearishMomentumBars[i];
|
|
|
|
//
|
|
XCBearishMomentumBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishMomentumBar(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Rejection Bars ...
|
|
int rejectionBarsCount = ArraySize(conditions.bearishRejectionBars);
|
|
if (drawRejectionBars &&
|
|
IsValidSize(rejectionBarsCount))
|
|
{
|
|
//
|
|
for (int i = 0; i < rejectionBarsCount; i++)
|
|
{
|
|
//
|
|
XOHCL iBar = conditions.bearishRejectionBars[i];
|
|
|
|
//
|
|
XCBearishRejectionBarObject *iObj;
|
|
bool isCreated = mPOIDrawer.CreateBearishRejectionBar(
|
|
iBar,
|
|
iObj //
|
|
);
|
|
if (isCreated)
|
|
{
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
// |