2424 lines
137 KiB
Plaintext
2424 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 ...
|
|
|
|
//
|
|
ENUM_X_POSITION_TYPES breakeType;
|
|
bool isBreaked = IsRangeBreaked(breakeType);
|
|
if (isBreaked)
|
|
{
|
|
//
|
|
Print("Breaked");
|
|
}
|
|
|
|
//
|
|
// 1- First Step is Find a Supply and Demand Zone ...
|
|
// - [] this Zone must be Fresh ...
|
|
// - [] contains Engulfing ...
|
|
// - [] has Order Block ...
|
|
// - [] has FVG ...
|
|
bool isDetected = DetectRange();
|
|
result = isDetected;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ClearDraws();
|
|
DrawRange();
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
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 //
|
|
);
|
|
}
|
|
|
|
//
|
|
// XCHVWAP ...
|
|
|
|
//
|
|
XRange mVWAPRange;
|
|
int mVWAPRangeLongBreakeouts;
|
|
int mVWAPRangeShortBreakeouts;
|
|
bool DetectRange()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int cIndex = 1;
|
|
int loopback = 7;
|
|
int dest = cIndex + loopback;
|
|
string symbol = GetSymbol();
|
|
datetime cTime = TimeCurrent();
|
|
ENUM_TIMEFRAMES period = GetPeriod();
|
|
|
|
//
|
|
// Reading Indicator's Conditions ...
|
|
XCHVWAPConditions chvwapConditions;
|
|
chvwapHelper.GetConditions(
|
|
chvwapConditions,
|
|
cIndex,
|
|
loopback //
|
|
);
|
|
|
|
//
|
|
mVWAPRange.symbol = symbol;
|
|
mVWAPRange.period = period;
|
|
|
|
//
|
|
// Find Range Start ...
|
|
if (!mVWAPRange.IsValid())
|
|
{
|
|
//
|
|
bool hasTouchedMedium = false;
|
|
bool hasTouchedLong = false;
|
|
bool hasTouchedHind = false;
|
|
|
|
//
|
|
int count = ArraySize(chvwapConditions.h);
|
|
result = IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
ENUM_XCHVWAP_STATES mState =
|
|
chvwapHelper.ToState(chvwapConditions.mState[i]);
|
|
if (!hasTouchedMedium &&
|
|
mState == XCHVWAP_NEUTURAL_STATE)
|
|
{
|
|
hasTouchedMedium = true;
|
|
}
|
|
|
|
//
|
|
ENUM_XCHVWAP_STATES lState =
|
|
chvwapHelper.ToState(chvwapConditions.lState[i]);
|
|
if (!hasTouchedLong &&
|
|
lState == XCHVWAP_NEUTURAL_STATE)
|
|
{
|
|
hasTouchedLong = true;
|
|
}
|
|
|
|
//
|
|
ENUM_XCHVWAP_STATES hState =
|
|
chvwapHelper.ToState(chvwapConditions.hState[i]);
|
|
if (!hasTouchedHind &&
|
|
hState == XCHVWAP_NEUTURAL_STATE)
|
|
{
|
|
hasTouchedHind = true;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
hasTouchedMedium &&
|
|
hasTouchedLong &&
|
|
hasTouchedHind
|
|
//
|
|
;
|
|
if (result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
XOHCL sBar;
|
|
result = sBar.Init(
|
|
symbol,
|
|
period,
|
|
dest //
|
|
);
|
|
if (result)
|
|
{
|
|
//
|
|
mVWAPRange.from = sBar.time;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
if (IsValid(mVWAPRange.from))
|
|
{
|
|
//
|
|
mVWAPRange.to = cTime;
|
|
|
|
//
|
|
int highIDX = iHighest(
|
|
symbol,
|
|
period,
|
|
MODE_HIGH,
|
|
dest,
|
|
cIndex //
|
|
);
|
|
double high = iHigh(
|
|
symbol,
|
|
period,
|
|
highIDX //
|
|
);
|
|
|
|
//
|
|
int lowIDX = iLowest(
|
|
symbol,
|
|
period,
|
|
MODE_LOW,
|
|
dest,
|
|
cIndex //
|
|
);
|
|
double low = iLow(
|
|
symbol,
|
|
period,
|
|
lowIDX //
|
|
);
|
|
|
|
//
|
|
if (mVWAPRange.upper == 0 ||
|
|
high > mVWAPRange.upper)
|
|
{
|
|
mVWAPRange.upper = high;
|
|
}
|
|
|
|
//
|
|
if (mVWAPRange.lower == 0 ||
|
|
low < mVWAPRange.lower)
|
|
{
|
|
mVWAPRange.lower = low;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = mVWAPRange.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool IsRangeBreaked(
|
|
ENUM_X_POSITION_TYPES &type //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
type = X_POSITION_TYPE_NONE;
|
|
|
|
//
|
|
int zIndex = 0;
|
|
int cIndex = zIndex + 1;
|
|
int pIndex = cIndex + 1;
|
|
|
|
//
|
|
int loopback = 7;
|
|
int dest = cIndex + loopback;
|
|
string symbol = GetSymbol();
|
|
datetime cTime = TimeCurrent();
|
|
ENUM_TIMEFRAMES period = GetPeriod();
|
|
|
|
//
|
|
result = mVWAPRange.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Reading Indicator's Conditions ...
|
|
XCHVWAPConditions chvwapConditions;
|
|
chvwapHelper.GetConditions(
|
|
chvwapConditions,
|
|
cIndex,
|
|
loopback //
|
|
);
|
|
|
|
//
|
|
XOHCL zBar;
|
|
result = zBar.Init(
|
|
symbol,
|
|
period,
|
|
zIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL cBar;
|
|
result = cBar.Init(
|
|
symbol,
|
|
period,
|
|
cIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullishOrdered =
|
|
//
|
|
chvwapConditions.m[0] > chvwapConditions.l[0] &&
|
|
chvwapConditions.l[0] > chvwapConditions.h[0]
|
|
//
|
|
;
|
|
bool isBullishState =
|
|
//
|
|
chvwapHelper.IsBullish(chvwapConditions.mState[0]) &&
|
|
chvwapHelper.IsBullish(chvwapConditions.lState[0]) &&
|
|
chvwapHelper.IsBullish(chvwapConditions.hState[0])
|
|
//
|
|
;
|
|
bool isBullishBreaked = isBullishState &&
|
|
isBullishOrdered &&
|
|
cBar.IsStrong(50) &&
|
|
cBar.IsBullish() &&
|
|
zBar.low > mVWAPRange.upper &&
|
|
cBar.GetUp() > mVWAPRange.upper;
|
|
if (isBullishBreaked)
|
|
{
|
|
//
|
|
mVWAPRangeLongBreakeouts++;
|
|
type = X_POSITION_TYPE_LONG;
|
|
}
|
|
|
|
//
|
|
bool isBearishOrdered =
|
|
//
|
|
chvwapConditions.m[0] < chvwapConditions.l[0] &&
|
|
chvwapConditions.l[0] < chvwapConditions.h[0]
|
|
//
|
|
;
|
|
bool isBearishState =
|
|
//
|
|
chvwapHelper.IsBearish(chvwapConditions.mState[0]) &&
|
|
chvwapHelper.IsBearish(chvwapConditions.lState[0]) &&
|
|
chvwapHelper.IsBearish(chvwapConditions.hState[0])
|
|
//
|
|
;
|
|
bool isBearishBreaked = isBearishState &&
|
|
isBearishOrdered &&
|
|
// cBar.IsStrong(50) &&
|
|
cBar.IsBearish() &&
|
|
// zBar.high < mVWAPRange.lower &&
|
|
cBar.GetDown() < mVWAPRange.lower;
|
|
if (isBearishBreaked)
|
|
{
|
|
//
|
|
mVWAPRangeShortBreakeouts++;
|
|
type = X_POSITION_TYPE_SHORT;
|
|
}
|
|
|
|
//
|
|
result = isBullishBreaked ||
|
|
isBearishBreaked;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void ResetRange()
|
|
{
|
|
//
|
|
mVWAPRange.Clean();
|
|
mVWAPRangeLongBreakeouts = 0;
|
|
mVWAPRangeShortBreakeouts = 0;
|
|
}
|
|
|
|
//
|
|
void DrawRange()
|
|
{
|
|
//
|
|
bool canDraw = mVWAPRange.IsValid();
|
|
if (!canDraw)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
string name = mVWAPRange.GetTag();
|
|
string tooltip = mVWAPRange.GetTooltip();
|
|
|
|
//
|
|
CChartObjectRectangle *iObj;
|
|
iObj = new CChartObjectRectangle();
|
|
bool isCreated = iObj.Create(
|
|
ChartIdentification(),
|
|
name,
|
|
SubWindowIdentification(),
|
|
mVWAPRange.from,
|
|
mVWAPRange.upper,
|
|
mVWAPRange.to,
|
|
mVWAPRange.lower //
|
|
);
|
|
if (!isCreated)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
iObj.Width(1);
|
|
iObj.Color(clrAqua);
|
|
iObj.Style(STYLE_SOLID);
|
|
iObj.Tooltip(tooltip);
|
|
|
|
//
|
|
mDrawnObjects.Add(iObj);
|
|
}
|
|
|
|
//
|
|
// 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
// |