last ...
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,824 @@
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// SaherElm IT Center MQL5 X121 SMC Signal Class
|
||||
// -------------------------------------------------
|
||||
// Name: XWZ
|
||||
// Description: provide all Signalling functions ...
|
||||
//
|
||||
//
|
||||
// Maintainer:
|
||||
// ------------
|
||||
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
||||
//
|
||||
//////////////////////////////////////////////////////
|
||||
//
|
||||
// Global Properties ...
|
||||
#property library
|
||||
#property copyright "Copyright 2023, SaherElm IT Center"
|
||||
#property link "https://www.saherelm.ir"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
//
|
||||
// Imports ...
|
||||
// #include "../../Libraries/x-trade.lib"
|
||||
#include "../Classes/x-121.smc.market.cycle.helper.class.mq5"
|
||||
#include "../Libraries/x-121.smc.guard.lib.mq5"
|
||||
#include "../Libraries/x-121.smc.lib.mq5"
|
||||
|
||||
//
|
||||
enum ENUM_X121SMC_XWZ_PRIORITY
|
||||
{
|
||||
X121SMC_XWZ_PRIORITY_NONE,
|
||||
X121SMC_XWZ_PRIORITY_WEAK,
|
||||
X121SMC_XWZ_PRIORITY_LOW,
|
||||
X121SMC_XWZ_PRIORITY_REGULAR,
|
||||
X121SMC_XWZ_PRIORITY_HIGH,
|
||||
};
|
||||
|
||||
//
|
||||
struct X121SMCXWZWorkingZone
|
||||
{
|
||||
//
|
||||
string symbol;
|
||||
ENUM_TIMEFRAMES period;
|
||||
|
||||
//
|
||||
double upper;
|
||||
double lower;
|
||||
|
||||
//
|
||||
double zoneUpper;
|
||||
double zoneLower;
|
||||
|
||||
//
|
||||
double quarter1;
|
||||
double quarter2;
|
||||
double quarter3;
|
||||
|
||||
//
|
||||
datetime from;
|
||||
|
||||
//
|
||||
X121SMCXWZWorkingZone()
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
|
||||
//
|
||||
void Clean()
|
||||
{
|
||||
//
|
||||
upper = 0;
|
||||
lower = 0;
|
||||
quarter1 = 0;
|
||||
quarter2 = 0;
|
||||
quarter3 = 0;
|
||||
zoneLower = 0;
|
||||
zoneUpper = 0;
|
||||
|
||||
//
|
||||
from = NULL;
|
||||
symbol = NULL;
|
||||
period = NULL;
|
||||
|
||||
//
|
||||
ZeroMemory(this);
|
||||
}
|
||||
|
||||
//
|
||||
bool IsValid()
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result =
|
||||
lower > 0 &&
|
||||
upper > 0 &&
|
||||
quarter1 > 0 &&
|
||||
quarter2 > 0 &&
|
||||
quarter3 > 0 &&
|
||||
upper > lower &&
|
||||
zoneLower > 0 &&
|
||||
zoneUpper > 0 &&
|
||||
IsValid(from) &&
|
||||
IsValid(symbol) &&
|
||||
IsValid(period) &&
|
||||
zoneUpper > upper &&
|
||||
zoneLower < lower;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool DetectOveralTrend(
|
||||
XOHCL &touchedBar,
|
||||
ENUM_X_DIRECTION &trendDir,
|
||||
int barIndex = 0 //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
if (barIndex < 0)
|
||||
{
|
||||
barIndex = 0;
|
||||
}
|
||||
|
||||
//
|
||||
trendDir = X_DIRECTION_NONE;
|
||||
|
||||
//
|
||||
result = IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int fromBarIndex = iBarShift(
|
||||
symbol,
|
||||
period,
|
||||
from //
|
||||
);
|
||||
result = IsValidIndex(fromBarIndex);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
XOHCL nearestUpperTouchedBar;
|
||||
XOHCL nearestLowerTouchedBar;
|
||||
bool hasNearestUpperTouchedBar = false;
|
||||
bool hasNearestLowerTouchedBar = false;
|
||||
for (int i = barIndex; i < fromBarIndex; i++)
|
||||
{
|
||||
//
|
||||
XOHCL iBar;
|
||||
bool isInited = iBar.Init(
|
||||
symbol,
|
||||
period,
|
||||
i //
|
||||
);
|
||||
|
||||
//
|
||||
hasNearestUpperTouchedBar = nearestUpperTouchedBar.IsValid();
|
||||
if (!hasNearestUpperTouchedBar)
|
||||
{
|
||||
//
|
||||
bool isBarTouchedUpper = iBar.high > upper;
|
||||
if (isBarTouchedUpper)
|
||||
{
|
||||
//
|
||||
nearestUpperTouchedBar = iBar;
|
||||
hasNearestUpperTouchedBar = true;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
hasNearestLowerTouchedBar = nearestLowerTouchedBar.IsValid();
|
||||
if (!hasNearestLowerTouchedBar)
|
||||
{
|
||||
//
|
||||
bool isBarTouchedLower = iBar.low < lower;
|
||||
if (isBarTouchedLower)
|
||||
{
|
||||
//
|
||||
nearestLowerTouchedBar = iBar;
|
||||
hasNearestLowerTouchedBar = true;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
if (hasNearestUpperTouchedBar &&
|
||||
hasNearestLowerTouchedBar)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
result = hasNearestUpperTouchedBar ||
|
||||
hasNearestLowerTouchedBar;
|
||||
if (result)
|
||||
{
|
||||
//
|
||||
if (hasNearestUpperTouchedBar &&
|
||||
!hasNearestLowerTouchedBar)
|
||||
{
|
||||
//
|
||||
trendDir = X_DIRECTION_BEARISH;
|
||||
touchedBar = nearestUpperTouchedBar;
|
||||
}
|
||||
else if (!hasNearestUpperTouchedBar &&
|
||||
hasNearestLowerTouchedBar)
|
||||
{
|
||||
//
|
||||
trendDir = X_DIRECTION_BULLISH;
|
||||
touchedBar = nearestLowerTouchedBar;
|
||||
}
|
||||
else if (hasNearestUpperTouchedBar &&
|
||||
hasNearestLowerTouchedBar)
|
||||
{
|
||||
//
|
||||
trendDir =
|
||||
nearestUpperTouchedBar.time < nearestLowerTouchedBar.time
|
||||
? X_DIRECTION_BULLISH
|
||||
: X_DIRECTION_BEARISH;
|
||||
|
||||
//
|
||||
if (IsBullish(trendDir))
|
||||
{
|
||||
touchedBar = nearestLowerTouchedBar;
|
||||
}
|
||||
else
|
||||
{
|
||||
touchedBar = nearestUpperTouchedBar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool IsDestroyed(
|
||||
ENUM_X_DIRECTION &destroyedDir,
|
||||
int barIndex = 0,
|
||||
ENUM_TIMEFRAMES forPeriod = NULL //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
if (barIndex < 0)
|
||||
{
|
||||
barIndex = 0;
|
||||
}
|
||||
|
||||
//
|
||||
if (!IsValid(forPeriod))
|
||||
{
|
||||
forPeriod = period;
|
||||
}
|
||||
|
||||
//
|
||||
destroyedDir = X_DIRECTION_NONE;
|
||||
|
||||
//
|
||||
result = IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
XOHCL bar;
|
||||
result = bar.Init(
|
||||
symbol,
|
||||
forPeriod,
|
||||
barIndex //
|
||||
);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool isUpperBreaked =
|
||||
bar.high > zoneUpper &&
|
||||
bar.close > zoneUpper;
|
||||
|
||||
//
|
||||
bool isLowerBreaked =
|
||||
bar.low < zoneLower &&
|
||||
bar.close < zoneLower;
|
||||
|
||||
//
|
||||
result = isUpperBreaked ||
|
||||
isLowerBreaked;
|
||||
if (result)
|
||||
{
|
||||
//
|
||||
destroyedDir =
|
||||
isUpperBreaked
|
||||
? X_DIRECTION_BULLISH
|
||||
: X_DIRECTION_BEARISH;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
};
|
||||
|
||||
//
|
||||
// Definitions ...
|
||||
struct X121SMCStrategyXWZSignalConditions
|
||||
{
|
||||
//
|
||||
// Props ...
|
||||
|
||||
//
|
||||
string symbol;
|
||||
ENUM_TIMEFRAMES period;
|
||||
|
||||
//
|
||||
double sl;
|
||||
double target;
|
||||
double reward;
|
||||
double amountPercent;
|
||||
ENUM_X_DIRECTION dir;
|
||||
ENUM_X_POSITION_TYPES type;
|
||||
|
||||
//
|
||||
// Setup Props ...
|
||||
|
||||
//
|
||||
datetime setupTime;
|
||||
datetime triggerTime;
|
||||
|
||||
//
|
||||
double pivot;
|
||||
double point;
|
||||
|
||||
//
|
||||
ENUM_X121SMC_XWZ_PRIORITY priority;
|
||||
|
||||
//
|
||||
// Working Zone ...
|
||||
|
||||
//
|
||||
XCFVG *fairValueGap;
|
||||
XCOrderBlock *orderBlock;
|
||||
XCSupplyZone *supplyZone;
|
||||
XCDemandZone *demandZone;
|
||||
X121SMCXWZWorkingZone workingZone;
|
||||
|
||||
//
|
||||
// Constructor ...
|
||||
X121SMCStrategyXWZSignalConditions()
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
|
||||
//
|
||||
// Tools ...
|
||||
|
||||
/**
|
||||
* Cleaning Up ...
|
||||
*/
|
||||
void Clean()
|
||||
{
|
||||
//
|
||||
sl = 0;
|
||||
target = 0;
|
||||
|
||||
//
|
||||
dir = X_DIRECTION_NONE;
|
||||
type = X_POSITION_TYPE_NONE;
|
||||
|
||||
//
|
||||
symbol = NULL;
|
||||
period = NULL;
|
||||
setupTime = NULL;
|
||||
triggerTime = NULL;
|
||||
|
||||
//
|
||||
ExtensionClean();
|
||||
|
||||
//
|
||||
ZeroMemory(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Condition is Setting Up ...
|
||||
*
|
||||
* @param dir: ENUM_X_DIRECTION member, Setting Up Direction ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool IsSetuped()
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result = IsValid(setupTime) &&
|
||||
HasDirection(dir);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate Setup Age ...
|
||||
*
|
||||
* @return ( int )
|
||||
*/
|
||||
int GetSetupAge()
|
||||
{
|
||||
//
|
||||
int result = 0;
|
||||
|
||||
//
|
||||
if (!IsSetuped())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result = (int)(TimeCurrent() - setupTime) / PeriodSeconds(period);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect How we Can Trigger Signal ...
|
||||
*
|
||||
* @return ( bool )
|
||||
*/
|
||||
bool CanTrigger()
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result =
|
||||
//
|
||||
sl > 0 &&
|
||||
IsValid(symbol) &&
|
||||
IsValid(period) &&
|
||||
IsValid(triggerTime) &&
|
||||
type != X_POSITION_TYPE_ALL &&
|
||||
type != X_POSITION_TYPE_NONE
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Extensions ...
|
||||
|
||||
/**
|
||||
* Clean Additional Properties ...
|
||||
*/
|
||||
void ExtensionClean()
|
||||
{
|
||||
//
|
||||
pivot = 0;
|
||||
point = 0;
|
||||
|
||||
//
|
||||
target = 0;
|
||||
reward = 0;
|
||||
amountPercent = 0;
|
||||
|
||||
//
|
||||
delete supplyZone;
|
||||
ZeroMemory(supplyZone);
|
||||
|
||||
//
|
||||
delete demandZone;
|
||||
ZeroMemory(demandZone);
|
||||
|
||||
//
|
||||
workingZone.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
//
|
||||
bool HasWorkingZone()
|
||||
{
|
||||
return workingZone.IsValid();
|
||||
}
|
||||
|
||||
//
|
||||
// Working Zone is an Area which
|
||||
// we decide to trade inside it ...
|
||||
bool ExtractWorkingZone(
|
||||
XPOIState &state //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result = !HasWorkingZone();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result = state.IsValid() &&
|
||||
state.HasChild() &&
|
||||
state.HasSupplyZones() &&
|
||||
state.HasDemandZones();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve Highest Supply Zone ...
|
||||
int hSupplyIDX = GetHighest(state.supplyZones);
|
||||
int lDemandIDX = GetLowest(state.demandZones);
|
||||
|
||||
//
|
||||
result =
|
||||
//
|
||||
IsValidIndex(hSupplyIDX) &&
|
||||
IsValidIndex(lDemandIDX)
|
||||
//
|
||||
;
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
supplyZone = state.supplyZones[hSupplyIDX];
|
||||
demandZone = state.demandZones[lDemandIDX];
|
||||
|
||||
//
|
||||
result =
|
||||
//
|
||||
supplyZone != NULL &&
|
||||
demandZone != NULL &&
|
||||
supplyZone.IsValid() &&
|
||||
demandZone.IsValid()
|
||||
//
|
||||
;
|
||||
if (!result)
|
||||
{
|
||||
//
|
||||
Clean();
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
workingZone.symbol = symbol;
|
||||
workingZone.period = period;
|
||||
|
||||
//
|
||||
workingZone.upper = supplyZone.Lower();
|
||||
workingZone.zoneUpper = supplyZone.Upper();
|
||||
|
||||
//
|
||||
workingZone.lower = demandZone.Upper();
|
||||
workingZone.zoneLower = demandZone.Lower();
|
||||
|
||||
//
|
||||
workingZone.from = MathMax(supplyZone.From(), demandZone.From());
|
||||
|
||||
//
|
||||
double upper = workingZone.upper;
|
||||
double range =
|
||||
workingZone.upper - workingZone.lower;
|
||||
double ranegPercent = range / 100;
|
||||
double quarterValue = ranegPercent * 25;
|
||||
|
||||
//
|
||||
workingZone.quarter1 = upper - (quarterValue * 1);
|
||||
workingZone.quarter2 = upper - (quarterValue * 2);
|
||||
workingZone.quarter3 = upper - (quarterValue * 3);
|
||||
|
||||
//
|
||||
result = workingZone.IsValid();
|
||||
if (!result)
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool IsWorkingZoneDestroyed(
|
||||
ENUM_X_DIRECTION &destroyedDir,
|
||||
int barIndex = 0,
|
||||
ENUM_TIMEFRAMES forPeriod = NULL //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
if (barIndex < 0)
|
||||
{
|
||||
barIndex = 0;
|
||||
}
|
||||
|
||||
//
|
||||
if (!IsValid(forPeriod))
|
||||
{
|
||||
forPeriod = period;
|
||||
}
|
||||
|
||||
//
|
||||
destroyedDir = X_DIRECTION_NONE;
|
||||
|
||||
//
|
||||
result = workingZone.IsValid();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
result = workingZone.IsDestroyed(
|
||||
destroyedDir,
|
||||
barIndex,
|
||||
forPeriod //
|
||||
);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool DetectTrend(
|
||||
ENUM_X_DIRECTION &trend,
|
||||
int barIndex = 0,
|
||||
ENUM_TIMEFRAMES forPeriod = NULL //
|
||||
)
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
if (barIndex < 0)
|
||||
{
|
||||
barIndex = 0;
|
||||
}
|
||||
|
||||
//
|
||||
if (forPeriod == NULL)
|
||||
{
|
||||
forPeriod = period;
|
||||
}
|
||||
|
||||
//
|
||||
trend = X_DIRECTION_NONE;
|
||||
|
||||
//
|
||||
result = HasWorkingZone();
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
int FromIndex = iBarShift(
|
||||
symbol,
|
||||
forPeriod,
|
||||
workingZone.from //
|
||||
);
|
||||
|
||||
//
|
||||
datetime supplyTouch = NULL;
|
||||
datetime demandTouch = NULL;
|
||||
for (int i = barIndex; i < FromIndex; i++)
|
||||
{
|
||||
//
|
||||
XOHCL iBar;
|
||||
bool isInited = iBar.Init(
|
||||
symbol,
|
||||
forPeriod,
|
||||
i //
|
||||
);
|
||||
if (!isInited)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
bool isTouchSupplyZone =
|
||||
//
|
||||
iBar.low < supplyZone.Lower() &&
|
||||
iBar.GetUp() > supplyZone.Lower()
|
||||
//
|
||||
;
|
||||
if (isTouchSupplyZone &&
|
||||
!IsValid(supplyTouch))
|
||||
{
|
||||
supplyTouch = iBar.time;
|
||||
}
|
||||
|
||||
//
|
||||
bool isTouchDemandZone =
|
||||
//
|
||||
iBar.high > demandZone.Upper() &&
|
||||
iBar.GetDown() < demandZone.Upper()
|
||||
//
|
||||
;
|
||||
if (isTouchDemandZone &&
|
||||
!IsValid(demandTouch))
|
||||
{
|
||||
demandTouch = iBar.time;
|
||||
}
|
||||
|
||||
//
|
||||
bool canBreak =
|
||||
IsValid(supplyTouch) &&
|
||||
IsValid(demandTouch);
|
||||
|
||||
//
|
||||
iBar.Clean();
|
||||
|
||||
//
|
||||
if (canBreak)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
result =
|
||||
//
|
||||
IsValid(supplyTouch) &&
|
||||
IsValid(demandTouch)
|
||||
//
|
||||
;
|
||||
if (result)
|
||||
{
|
||||
//
|
||||
trend =
|
||||
//
|
||||
supplyTouch > demandTouch
|
||||
? X_DIRECTION_BEARISH
|
||||
: X_DIRECTION_BULLISH
|
||||
//
|
||||
;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
bool HasOrderBlock()
|
||||
{
|
||||
return orderBlock != NULL &&
|
||||
orderBlock.IsValid();
|
||||
}
|
||||
|
||||
//
|
||||
bool HasFairValueGap()
|
||||
{
|
||||
return fairValueGap != NULL &&
|
||||
fairValueGap.IsValid();
|
||||
}
|
||||
|
||||
//
|
||||
void UpdateTo(datetime value = NULL)
|
||||
{
|
||||
//
|
||||
value = NormalizeTime(value);
|
||||
|
||||
//
|
||||
if (supplyZone != NULL)
|
||||
{
|
||||
supplyZone.To(value);
|
||||
}
|
||||
|
||||
//
|
||||
if (demandZone != NULL)
|
||||
{
|
||||
demandZone.To(value);
|
||||
}
|
||||
|
||||
//
|
||||
if (orderBlock != NULL)
|
||||
{
|
||||
orderBlock.To(value);
|
||||
}
|
||||
|
||||
//
|
||||
if (fairValueGap != NULL)
|
||||
{
|
||||
fairValueGap.To(value);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
};
|
||||
Reference in New Issue
Block a user