Files
MQL5Data/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5
T

2342 lines
135 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 "../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)
{
}
//
// 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;
}
//
// 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 = HasValidDemand(iConditions);
bool hasValidSupply = HasValidSupply(iConditions);
result = hasValidDemand || hasValidSupply;
if (!result)
{
break;
}
//
bool isPriceInsideDemandZone =
pBar.high < iConditions.demandZone.upper;
bool isPriceInsideSupplyZone =
pBar.low > iConditions.supplyZone.lower;
//
bool isTicksBullish = IsTicksBullish();
bool isTicksBearish = IsTicksBearish();
bool isTicksHasMomentum = IsTicksHasMomentum();
//
double _1Pip = GetPipPrice(iConditions.symbol);
//
// Longs ...
bool canCheckLong = isAllowLong &&
hasValidDemand &&
isTicksBullish &&
isTicksHasMomentum &&
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 Demand Zone ...
hasLong = slCandidatesCount > 2;
//
if (hasLong)
{
//
double selectedSL = GetMin(slCandidates);
sl = selectedSL - (5 * _1Pip);
risk = entry - sl;
reward = risk * r2r;
tp = entry + reward;
//
conditionsIDX = i;
mConditions[i].CleanDemand();
//
break;
}
}
//
// Shorts ...
bool canCheckShort = isAllowShort &&
hasValidSupply &&
isTicksBearish &&
isTicksHasMomentum &&
isPriceInsideSupplyZone;
if (canCheckShort)
{
//
hasShort = false;
DrawMarketStructure(
structure,
X_POSITION_TYPE_SHORT //
);
DrawConditions(iConditions);
ClearDraws();
//
if (hasShort)
{
//
type = POSITION_TYPE_SELL;
entry = GetEntry(_symbol, type);
sl = iConditions.supplyZone.upper + (10 * points);
risk = sl - entry;
reward = risk * r2r;
tp = entry - reward;
//
conditionsIDX = i;
mConditions[i].CleanSupply();
//
break;
}
}
}
//
result = hasLong ||
hasShort;
//
// Rmove Signal Condition ...
if (result)
{
//
if (IsValidIndex(conditionsIDX))
{
//
conditions = mConditions[conditionsIDX];
//
bool hasValidDemand = HasValidDemand(mConditions[conditionsIDX]);
bool hasValidSupply = HasValidSupply(mConditions[conditionsIDX]);
//
if (!hasValidDemand &&
!hasValidSupply)
{
//
ArrayRemove(
mConditions,
conditionsIDX,
1 //
);
}
}
//
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;
}
//
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;
//
// 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 = HasValidDemand(conditions);
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;
//
// 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 = HasValidSupply(conditions);
if (!hasValidSupplyZone)
{
conditions.CleanSupply();
}
else
{
break;
}
}
}
//
// Demand ...
// Used for Long ...
bool hasValidDemandZone = HasValidDemand(conditions);
//
// Supply ...
// Used for Short ...
bool hasValidSupplyZone = HasValidSupply(conditions);
//
// 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 = HasValidDemand(conditions);
bool hasValidSupply = HasValidSupply(conditions);
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 = HasValidSupply(conditions);
bool hasValidDemand = HasValidDemand(conditions);
if (!hasValidSupply && !hasValidDemand)
{
return;
}
//
int idx = -1;
for (int i = 0; i < count; i++)
{
//
X121SMCStrategyConditions iConditions = mConditions[i];
//
bool isSupplySame =
hasValidSupply &&
HasValidSupply(iConditions) &&
conditions.supplyZone.from == iConditions.supplyZone.from &&
conditions.supplyZone.upper == iConditions.supplyZone.upper &&
conditions.supplyZone.lower == iConditions.supplyZone.lower;
bool isDemandSame =
hasValidDemand &&
HasValidDemand(iConditions) &&
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:
//
//
// 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 = HasValidDemand(conditions);
bool hasValidSupply = HasValidSupply(conditions);
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;
}
/**
* Check Conditions has Valid Demand ...
*
* @param conditions: X121SMCStrategyConditions instance ...
*
* @return ( bool )
*/
bool HasValidDemand(X121SMCStrategyConditions &conditions)
{
//
bool result = false;
//
result = conditions.IsValid();
if (!result)
{
return result;
}
//
result =
//
conditions.demandZone.IsValid() &&
(ArraySize(conditions.supports) > 0 ||
ArraySize(conditions.swingLows) > 0 ||
ArraySize(conditions.bullishFVGs) > 0 ||
ArraySize(conditions.bullishOrderBlocks) > 0 ||
ArraySize(conditions.bullishMomentumBars) > 0 ||
ArraySize(conditions.bullishRejectionBars) > 0)
//
;
//
return result;
}
/**
* Check Conditions has Valid Supply ...
*
* @param conditions: X121SMCStrategyConditions instance ...
*
* @return ( bool )
*/
bool HasValidSupply(X121SMCStrategyConditions &conditions)
{
//
bool result = false;
//
result = conditions.IsValid();
if (!result)
{
return result;
}
//
result =
//
conditions.supplyZone.IsValid() &&
(ArraySize(conditions.swingHighs) > 0 ||
ArraySize(conditions.bearishFVGs) > 0 ||
ArraySize(conditions.resistances) > 0 ||
ArraySize(conditions.bearishOrderBlocks) > 0 ||
ArraySize(conditions.bearishMomentumBars) > 0 ||
ArraySize(conditions.bearishRejectionBars) > 0)
//
;
//
return result;
}
//
// Draw Functions ...
/**
* Draw Specific Condition ...
*
* @param conditions: X121SMCStrategyConditions instance ...
*/
void DrawConditions(X121SMCStrategyConditions &conditions)
{
//
if (!conditions.IsValid())
{
return;
}
//
datetime time = TimeCurrent();
bool hasValidDemand = HasValidDemand(conditions);
bool hasValidSupply = HasValidSupply(conditions);
if (!hasValidDemand && !hasValidSupply)
{
return;
}
//
// Demand Zone ...
if (hasValidDemand)
{
//
// Demand ...
XCDemandZoneObject *iObj;
bool isCreated = mPOIDrawer.CreateDemandZone(
conditions.demandZone,
iObj //
);
if (isCreated)
{
//
// RemoveObject(iObj.ObjName());
mDrawnObjects.Add(iObj);
}
//
// Order Blocks ...
int obsCount = ArraySize(conditions.bullishOrderBlocks);
if (IsValidSize(obsCount))
{
//
for (int i = 0; i < obsCount; i++)
{
//
XZone iZone = conditions.bullishOrderBlocks[i];
//
XCBullishOrderBlockObject *iObj;
bool isCreated = mPOIDrawer.CreateBullishOrderBlock(
iZone,
iObj //
);
if (isCreated)
{
//
// RemoveObject(iObj.ObjName());
mDrawnObjects.Add(iObj);
}
}
}
//
// Fair Value Gaps ...
int fvgsCount = ArraySize(conditions.bullishFVGs);
if (IsValidSize(fvgsCount))
{
//
for (int i = 0; i < fvgsCount; i++)
{
//
XZone iZone = conditions.bullishFVGs[i];
//
XCBullishFVGObject *iObj;
bool isCreated = mPOIDrawer.CreateBullishFVG(
iZone,
iObj //
);
if (isCreated)
{
//
// RemoveObject(iObj.ObjName());
mDrawnObjects.Add(iObj);
}
}
}
//
// Supports ...
int supportsCount = ArraySize(conditions.supports);
if (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)
{
//
// RemoveObject(iObj.ObjName());
mDrawnObjects.Add(iObj);
}
}
}
//
// Swings ...
int swingsCount = ArraySize(conditions.swingLows);
if (IsValidSize(swingsCount))
{
//
for (int i = 0; i < swingsCount; i++)
{
//
XOHCL iBar = conditions.swingLows[i];
//
XCSwingLowObject *iObj;
bool isCreated = mPOIDrawer.CreateSwingLow(
iBar,
iObj //
);
if (isCreated)
{
//
// RemoveObject(iObj.ObjName());
mDrawnObjects.Add(iObj);
}
}
}
//
// Momentum Bars ...
int momentumBarsCount = ArraySize(conditions.bullishMomentumBars);
if (IsValidSize(momentumBarsCount))
{
//
for (int i = 0; i < momentumBarsCount; i++)
{
//
XOHCL iBar = conditions.bullishMomentumBars[i];
//
XCBullishMomentumBarObject *iObj;
bool isCreated = mPOIDrawer.CreateBullishMomentumBar(
iBar,
iObj //
);
if (isCreated)
{
//
// RemoveObject(iObj.ObjName());
mDrawnObjects.Add(iObj);
}
}
}
//
// Rejection Bars ...
int rejectionBarsCount = ArraySize(conditions.bullishRejectionBars);
if (IsValidSize(rejectionBarsCount))
{
//
for (int i = 0; i < rejectionBarsCount; i++)
{
//
XOHCL iBar = conditions.bullishRejectionBars[i];
//
XCBullishRejectionBarObject *iObj;
bool isCreated = mPOIDrawer.CreateBullishRejectionBar(
iBar,
iObj //
);
if (isCreated)
{
//
// RemoveObject(iObj.ObjName());
mDrawnObjects.Add(iObj);
}
}
}
}
//
// Supply Zone ...
if (hasValidSupply)
{
//
// Supply ...
XCSupplyZoneObject *iObj;
bool isCreated = mPOIDrawer.CreateSupplyZone(
conditions.supplyZone,
iObj //
);
if (isCreated)
{
//
// RemoveObject(iObj.ObjName());
mDrawnObjects.Add(iObj);
}
//
// Order Blocks ...
int obsCount = ArraySize(conditions.bearishOrderBlocks);
if (IsValidSize(obsCount))
{
//
for (int i = 0; i < obsCount; i++)
{
//
XZone iZone = conditions.bearishOrderBlocks[i];
//
XCBearishOrderBlockObject *iObj;
bool isCreated = mPOIDrawer.CreateBearishOrderBlock(
iZone,
iObj //
);
if (isCreated)
{
//
// RemoveObject(iObj.ObjName());
mDrawnObjects.Add(iObj);
}
}
}
//
// Fair Value Gaps ...
int fvgsCount = ArraySize(conditions.bearishFVGs);
if (IsValidSize(fvgsCount))
{
//
for (int i = 0; i < fvgsCount; i++)
{
//
XZone iZone = conditions.bearishFVGs[i];
//
XCBearishFVGObject *iObj;
bool isCreated = mPOIDrawer.CreateBearishFVG(
iZone,
iObj //
);
if (isCreated)
{
//
// RemoveObject(iObj.ObjName());
mDrawnObjects.Add(iObj);
}
}
}
//
// Resistances ...
int resistancesCount = ArraySize(conditions.resistances);
if (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)
{
//
// RemoveObject(iObj.ObjName());
mDrawnObjects.Add(iObj);
}
}
}
//
// Swings ...
int swingsCount = ArraySize(conditions.swingHighs);
if (IsValidSize(swingsCount))
{
//
for (int i = 0; i < swingsCount; i++)
{
//
XOHCL iBar = conditions.swingHighs[i];
//
XCSwingHighObject *iObj;
bool isCreated = mPOIDrawer.CreateSwingHigh(
iBar,
iObj //
);
if (isCreated)
{
//
// RemoveObject(iObj.ObjName());
mDrawnObjects.Add(iObj);
}
}
}
//
// Momentum Bars ...
int momentumBarsCount = ArraySize(conditions.bearishMomentumBars);
if (IsValidSize(momentumBarsCount))
{
//
for (int i = 0; i < momentumBarsCount; i++)
{
//
XOHCL iBar = conditions.bearishMomentumBars[i];
//
XCBearishMomentumBarObject *iObj;
bool isCreated = mPOIDrawer.CreateBearishMomentumBar(
iBar,
iObj //
);
if (isCreated)
{
//
// RemoveObject(iObj.ObjName());
mDrawnObjects.Add(iObj);
}
}
}
//
// Rejection Bars ...
int rejectionBarsCount = ArraySize(conditions.bearishRejectionBars);
if (IsValidSize(rejectionBarsCount))
{
//
for (int i = 0; i < rejectionBarsCount; i++)
{
//
XOHCL iBar = conditions.bearishRejectionBars[i];
//
XCBearishRejectionBarObject *iObj;
bool isCreated = mPOIDrawer.CreateBearishRejectionBar(
iBar,
iObj //
);
if (isCreated)
{
//
// RemoveObject(iObj.ObjName());
mDrawnObjects.Add(iObj);
}
}
}
}
}
/**
* Draw Specified Market Struture ...
*
* @param structure: X121SMCMarketStructure instance ...
*/
void DrawMarketStructure(
X121SMCMarketStructure &structure,
ENUM_X_POSITION_TYPES type = X_POSITION_TYPE_ALL //
)
{
//
datetime cTime = TimeCurrent();
//
bool canAll = type == X_POSITION_TYPE_ALL;
bool canLong = type == X_POSITION_TYPE_LONG;
bool canShort = type == X_POSITION_TYPE_SHORT;
//
// Supply Zones ...
int supplysCount = ArraySize(structure.supplyZones);
if ((canAll || canLong) && IsValidSize(supplysCount))
{
//
for (int i = 0; i < supplysCount; i++)
{
//
XZone iZone = structure.supplyZones[i];
//
XCSupplyZoneObject *iObj;
bool isCreated = mPOIDrawer.CreateSupplyZone(
iZone,
iObj //
);
if (isCreated)
{
//
mDrawnObjects.Add(iObj);
}
}
}
//
// Demand Zones ...
int demandsCount = ArraySize(structure.demandZones);
if ((canAll || canShort) && IsValidSize(demandsCount))
{
//
for (int i = 0; i < demandsCount; i++)
{
//
XZone iZone = structure.demandZones[i];
//
XCDemandZoneObject *iObj;
bool isCreated = mPOIDrawer.CreateDemandZone(
iZone,
iObj //
);
if (isCreated)
{
//
mDrawnObjects.Add(iObj);
}
}
}
//
// Order Blocks ...
//
// Bullish OBs ...
int bullishOBsCount = ArraySize(structure.bullishOrderBlocks);
if ((canAll || canShort) && IsValidSize(bullishOBsCount))
{
//
for (int i = 0; i < bullishOBsCount; i++)
{
//
XZone iZone = structure.bullishOrderBlocks[i];
//
XCBullishOrderBlockObject *iObj;
bool isCreated = mPOIDrawer.CreateBullishOrderBlock(
iZone,
iObj //
);
if (isCreated)
{
//
mDrawnObjects.Add(iObj);
}
}
}
//
// Bearish OBs ...
int bearishOBsCount = ArraySize(structure.bearishOrderBlocks);
if ((canAll || canLong) && IsValidSize(bearishOBsCount))
{
//
for (int i = 0; i < bearishOBsCount; i++)
{
//
XZone iZone = structure.bearishOrderBlocks[i];
//
XCBearishOrderBlockObject *iObj;
bool isCreated = mPOIDrawer.CreateBearishOrderBlock(
iZone,
iObj //
);
if (isCreated)
{
//
mDrawnObjects.Add(iObj);
}
}
}
//
// Fair Value Gaps ...
//
// Bullish FVGs ...
int bullishFVGsCount = ArraySize(structure.bullishFVGs);
if ((canAll || canShort) && IsValidSize(bullishFVGsCount))
{
//
for (int i = 0; i < bullishFVGsCount; i++)
{
//
XZone iZone = structure.bullishFVGs[i];
//
XCBullishFVGObject *iObj;
bool isCreated = mPOIDrawer.CreateBullishFVG(
iZone,
iObj //
);
if (isCreated)
{
//
mDrawnObjects.Add(iObj);
}
}
}
//
// Bearish FVGs ...
int bearishFVGsCount = ArraySize(structure.bearishFVGs);
if ((canAll || canLong) && IsValidSize(bearishFVGsCount))
{
//
for (int i = 0; i < bearishFVGsCount; i++)
{
//
XZone iZone = structure.bearishFVGs[i];
//
XCBearishFVGObject *iObj;
bool isCreated = mPOIDrawer.CreateBearishFVG(
iZone,
iObj //
);
if (isCreated)
{
//
mDrawnObjects.Add(iObj);
}
}
}
//
// Swing Highs ...
int swingHighsCount = ArraySize(structure.swingHighs);
if ((canAll || canLong) && IsValidSize(swingHighsCount))
{
//
for (int i = 0; i < swingHighsCount; i++)
{
//
XOHCL iBar = structure.swingHighs[i];
//
XCSwingHighObject *iObj;
bool isCreated = mPOIDrawer.CreateSwingHigh(
iBar,
iObj //
);
if (isCreated)
{
//
mDrawnObjects.Add(iObj);
}
}
}
//
// Swing Lows ...
int swingLowsCount = ArraySize(structure.swingLows);
if ((canAll || canShort) && IsValidSize(swingLowsCount))
{
//
for (int i = 0; i < swingLowsCount; i++)
{
//
XOHCL iBar = structure.swingLows[i];
//
XCSwingLowObject *iObj;
bool isCreated = mPOIDrawer.CreateSwingLow(
iBar,
iObj //
);
if (isCreated)
{
//
mDrawnObjects.Add(iObj);
}
}
}
//
// Support Zones ...
int supportsCount = ArraySize(structure.supports);
if ((canAll || canShort) && IsValidSize(supportsCount))
{
//
for (int i = 0; i < supportsCount; i++)
{
//
XOHCL iBar = structure.supports[i];
//
XCSupportZoneObject *iObj;
bool isCreated = mPOIDrawer.CreateSupportZone(
iBar,
iObj,
cTime //
);
if (isCreated)
{
//
mDrawnObjects.Add(iObj);
}
}
}
//
// Resistance Zones ...
int resistancesCount = ArraySize(structure.resistances);
if ((canAll || canLong) && IsValidSize(resistancesCount))
{
//
for (int i = 0; i < resistancesCount; i++)
{
//
XOHCL iBar = structure.resistances[i];
//
XCResistanceZoneObject *iObj;
bool isCreated = mPOIDrawer.CreateResistanceZone(
iBar,
iObj,
cTime //
);
if (isCreated)
{
//
mDrawnObjects.Add(iObj);
}
}
}
//
// Momentum Bars ...
//
// Bullish Momentum Bars ...
int momentumBarCount = ArraySize(structure.bullishMomentumBars);
if ((canAll || canShort) && IsValidSize(momentumBarCount))
{
//
for (int i = 0; i < momentumBarCount; i++)
{
//
XOHCL iBar = structure.bullishMomentumBars[i];
//
XCBullishMomentumBarObject *iObj;
bool isCreated = mPOIDrawer.CreateBullishMomentumBar(
iBar,
iObj //
);
if (isCreated)
{
//
mDrawnObjects.Add(iObj);
}
}
}
//
// Bearish Momentum Bars ...
momentumBarCount = ArraySize(structure.bearishMomentumBars);
if ((canAll || canLong) && IsValidSize(momentumBarCount))
{
//
for (int i = 0; i < momentumBarCount; i++)
{
//
XOHCL iBar = structure.bearishMomentumBars[i];
//
XCBearishMomentumBarObject *iObj;
bool isCreated = mPOIDrawer.CreateBearishMomentumBar(
iBar,
iObj //
);
if (isCreated)
{
//
mDrawnObjects.Add(iObj);
}
}
}
//
// Rejection Bars ...
//
// Bullish Rejection Bars ...
int rejectionBarCount = ArraySize(structure.bullishRejectionBars);
if ((canAll || canShort) && IsValidSize(rejectionBarCount))
{
//
for (int i = 0; i < rejectionBarCount; i++)
{
//
XOHCL iBar = structure.bullishRejectionBars[i];
//
XCBullishRejectionBarObject *iObj;
bool isCreated = mPOIDrawer.CreateBullishRejectionBar(
iBar,
iObj //
);
if (isCreated)
{
//
mDrawnObjects.Add(iObj);
}
}
}
//
// Bearish Rejection Bars ...
rejectionBarCount = ArraySize(structure.bearishRejectionBars);
if ((canAll || canLong) && IsValidSize(rejectionBarCount))
{
//
for (int i = 0; i < rejectionBarCount; i++)
{
//
XOHCL iBar = structure.bearishRejectionBars[i];
//
XCBearishRejectionBarObject *iObj;
bool isCreated = mPOIDrawer.CreateBearishRejectionBar(
iBar,
iObj //
);
if (isCreated)
{
//
mDrawnObjects.Add(iObj);
}
}
}
}
//
};
//