Files
MQL5Data/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5
T
2024-11-06 05:52:24 +03:30

1188 lines
63 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 "../../Helpers/x-saherelm.xpv.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();
}
//
// Deconstructor ...
void ~XCX121SMCTestStrategy()
{
//
delete pvHelper;
delete chvwapHelper;
}
//
// 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;
//
bool isAllowLong = AllowLong();
bool isAllowShort = AllowShort();
result = isAllowLong || isAllowShort;
if (!result)
{
return result;
;
}
//
// Start Calculations ...
//
string _symbol = GetSymbol();
ENUM_TIMEFRAMES _period = GetPeriod();
//
double points = GetPoints(_symbol);
double pip = GetPipPrice(_symbol);
double pip2 = 2 * pip;
double pip3 = 3 * pip;
//
int zIndex = 0;
int cIndex = zIndex + 1;
int pIndex = cIndex + 1;
int ppIndex = pIndex + 1;
//
int loopback = 7;
string symbol = _symbol;
int dest = cIndex + loopback;
datetime cTime = TimeCurrent();
ENUM_TIMEFRAMES period = _period;
//
// 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;
}
//
// Reading Indicator's Conditions ...
XCHVWAPConditions chvwapConditions;
chvwapHelper.GetConditions(
chvwapConditions,
cIndex,
loopback //
);
//
// Select a Supply Zone which Price is Inside it ...
XZone supplyZone;
XZone aSupplyZone;
bool hasSupplyZoneArroundCBar = false;
int supplyZonesCount = ArraySize(_5MState.supplyZones);
bool hasSupplyZoneOverCBar = IsValidSize(supplyZonesCount);
if (hasSupplyZoneOverCBar)
{
//
hasSupplyZoneOverCBar = false;
for (int i = 0; i < supplyZonesCount; i++)
{
//
XZone iZone = _5MState.supplyZones[i];
//
if (!hasSupplyZoneOverCBar &&
iZone.lower > cBar.high)
{
//
iZone.to = cTime;
supplyZone = iZone;
hasSupplyZoneOverCBar = true;
// //
// break;
}
//
if ((!hasSupplyZoneArroundCBar &&
iZone.lower < cBar.low &&
iZone.upper > cBar.high) ||
(hasSupplyZoneArroundCBar &&
aSupplyZone.lower < cBar.low &&
aSupplyZone.upper > cBar.high &&
iZone.lower < cBar.low &&
iZone.upper > cBar.high &&
iZone.GetRange() < aSupplyZone.GetRange()))
{
aSupplyZone = iZone;
}
}
}
//
XZone demandZone;
int demandZonesCount = ArraySize(_5MState.demandZones);
bool hasDemandZoneUnderCBar = IsValidSize(demandZonesCount);
if (hasDemandZoneUnderCBar)
{
//
hasDemandZoneUnderCBar = false;
for (int i = 0; i < demandZonesCount; i++)
{
//
XZone iZone = _5MState.demandZones[i];
//
if (!hasDemandZoneUnderCBar &&
iZone.upper < cBar.low)
{
//
iZone.to = cTime;
demandZone = iZone;
hasDemandZoneUnderCBar = true;
//
break;
}
}
}
//
XOHCL swingHigh;
int swingHighsCount = ArraySize(_5MState.swingHighs);
bool hasSwingHighOverCBar = IsValidSize(swingHighsCount);
if (hasSwingHighOverCBar)
{
//
hasSwingHighOverCBar = false;
for (int i = 0; i < swingHighsCount; i++)
{
//
XOHCL iBar = _5MState.swingHighs[i];
//
if (!hasSwingHighOverCBar &&
iBar.high > cBar.high)
{
//
swingHigh = iBar;
hasSwingHighOverCBar = true;
//
break;
}
}
}
//
XOHCL swingLow;
int swingLowsCount = ArraySize(_5MState.swingLows);
bool hasSwingLowUnderCBar = IsValidSize(swingLowsCount);
if (hasSwingLowUnderCBar)
{
//
hasSwingLowUnderCBar = false;
for (int i = 0; i < swingLowsCount; i++)
{
//
XOHCL iBar = _5MState.swingLows[i];
//
if (!hasSwingLowUnderCBar &&
iBar.low < cBar.low)
{
//
swingLow = iBar;
hasSwingLowUnderCBar = true;
//
break;
}
}
}
//
XOHCL bullishRejectionBar;
XOHCL bearishRejectionBar;
bool hasBullishRejectionBarUnderCBar = false;
bool hasBearishRejectionBarOverCBar = false;
int rejectionBarsCount = ArraySize(_5MState.rejectionBars);
if (IsValidSize(rejectionBarsCount))
{
//
for (int i = 0; i < rejectionBarsCount; i++)
{
//
XOHCL iBar = _5MState.rejectionBars[i];
//
bool isBullish = iBar.GetLowShadow() > iBar.GetHighShadow();
bool isBearish = iBar.GetHighShadow() > iBar.GetLowShadow();
//
if (isBullish &&
!hasBullishRejectionBarUnderCBar &&
iBar.high < cBar.low)
{
//
bullishRejectionBar = iBar;
hasBullishRejectionBarUnderCBar = true;
}
//
if (isBearish &&
!hasBearishRejectionBarOverCBar &&
iBar.low > cBar.high)
{
//
bearishRejectionBar = iBar;
hasBearishRejectionBarOverCBar = true;
}
}
}
//
bool isBullish =
//
(
//
(
//
// Common Conditions ...
//
// Check Has Swing Low Under CBar ...
hasSwingLowUnderCBar &&
//
// Check has a Demand Zone Under CBar ...
hasDemandZoneUnderCBar &&
//
// Check Candle is Strong ...
cBar.IsBullishDecision() &&
//
// Check Has a Bullish Rejection Bar Under CBar ...
hasBullishRejectionBarUnderCBar &&
//
(
//
// First ...
(
//
cBar.open < chvwapConditions.s[0] &&
cBar.open < chvwapConditions.m[0] &&
cBar.open < chvwapConditions.l[0] &&
cBar.open < chvwapConditions.h[0] &&
//
cBar.close > chvwapConditions.s[0] &&
cBar.close > chvwapConditions.m[0] &&
cBar.close > chvwapConditions.l[0] &&
cBar.close > chvwapConditions.h[0]
//
)
//
||
//
// Seccend ...
(
//
chvwapConditions.s[0] > chvwapConditions.m[0] &&
chvwapConditions.m[0] > chvwapConditions.l[0] &&
chvwapConditions.l[0] > chvwapConditions.h[0] &&
//
cBar.close > chvwapConditions.s[0]
//
)
//
)
//
)
//
);
//
bool isBearish =
//
(
//
(
//
// Common Conditions ...
//
// Check Has Swing High Over CBar ...
hasSwingHighOverCBar &&
//
// Check Has Supply Zone Over CBar ...
hasSupplyZoneOverCBar &&
//
// Check Candle is Strong ...
cBar.IsBearishDecision() &&
//
// Check Has a Bearish Rejection Bar Over CBar ...
hasBearishRejectionBarOverCBar &&
//
(
//
// First ...
(
//
cBar.open > chvwapConditions.s[0] &&
cBar.open > chvwapConditions.m[0] &&
cBar.open > chvwapConditions.l[0] &&
cBar.open > chvwapConditions.h[0] &&
//
cBar.close < chvwapConditions.s[0] &&
cBar.close < chvwapConditions.m[0] &&
cBar.close < chvwapConditions.l[0] &&
cBar.close < chvwapConditions.h[0]
//
)
//
||
//
// Second ...
(
//
chvwapConditions.s[0] < chvwapConditions.m[0] &&
chvwapConditions.m[0] < chvwapConditions.l[0] &&
chvwapConditions.l[0] < chvwapConditions.h[0] &&
//
cBar.close < chvwapConditions.s[0]
//
)
//
)
//
)
//
);
//
if (isBullish || isBearish)
{
//
double pvPOIss[];
DetectPVPOIs(
pvPOIss //
);
//
// Draw supply if Exists ...
if (hasSupplyZoneOverCBar)
{
//
XCSupplyZoneObject *iObj;
bool isCreated = mPOIDrawer.CreateSupplyZone(
supplyZone,
iObj //
);
if (isCreated)
{
mDrawnObjects.Add(iObj);
}
}
//
// Draw Demand if Exists ...
if (hasDemandZoneUnderCBar)
{
//
XCDemandZoneObject *iObj;
bool isCreated = mPOIDrawer.CreateDemandZone(
demandZone,
iObj //
);
if (isCreated)
{
mDrawnObjects.Add(iObj);
}
}
//
// Draw Swing High ...
if (hasSwingHighOverCBar)
{
//
XCSwingHighObject *iObj;
bool isCreated = mPOIDrawer.CreateSwingHigh(
swingHigh,
iObj //
);
if (isCreated)
{
mDrawnObjects.Add(iObj);
}
}
//
// Draw Swing Low ...
if (hasSwingLowUnderCBar)
{
//
XCSwingLowObject *iObj;
bool isCreated = mPOIDrawer.CreateSwingLow(
swingLow,
iObj //
);
if (isCreated)
{
mDrawnObjects.Add(iObj);
}
}
//
// Draw Bullish Rejection Bar ...
if (hasBullishRejectionBarUnderCBar)
{
//
XCBullishRejectionBarObject *iObj;
bool isCreated = mPOIDrawer.CreateBullishRejectionBar(
bullishRejectionBar,
iObj //
);
if (isCreated)
{
mDrawnObjects.Add(iObj);
}
}
//
// Draw Bearish Rejection Bar ...
if (hasBearishRejectionBarOverCBar)
{
//
XCBearishRejectionBarObject *iObj;
bool isCreated = mPOIDrawer.CreateBearishRejectionBar(
bearishRejectionBar,
iObj //
);
if (isCreated)
{
mDrawnObjects.Add(iObj);
}
}
//
Print("");
// hasLong = isBullish;
// hasShort = isBearish;
}
//
result = hasLong ||
hasShort;
if (!result)
{
conditions.Clean();
}
//
// Rmove Signal Condition ...
if (result)
{
//
// TYPE ...
type =
hasLong
? POSITION_TYPE_BUY
: POSITION_TYPE_SELL;
ENUM_X_POSITION_TYPES xType =
hasLong
? X_POSITION_TYPE_LONG
: X_POSITION_TYPE_SHORT;
//
entry = GetEntry(
conditions.symbol,
type //
);
//
double slCandidates[];
//
double selectedSL =
hasLong
? GetMin(slCandidates)
: GetMax(slCandidates);
sl =
hasLong
? selectedSL - pip3
: selectedSL + pip3;
//
// RISK Reward ...
risk =
hasLong
? entry - sl
: sl - entry;
reward = risk * r2r;
tp =
hasLong
? entry + reward
: entry - reward;
//
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;
}
//
// Customize Strategy Identifier ...
string GetTag() override
{
return X121SMCSUPDEMStrategyToken;
}
//
// Protected ...
protected:
//
//
// Props ...
//
// XPV ...
XPVInputs pvInputs;
XSCXPVHelper *pvHelper;
//
// XCHVWAP ...
XCHVWAPInputs chvwapInputs;
XSCXCHVWAPHelper *chvwapHelper;
//
// Private ...
private:
//
// Props ...
/**
* Initial Required Indicators Helper ...
*/
void InitialHelpers()
{
//
string symbol = GetSymbol();
ENUM_TIMEFRAMES period = GetPeriod();
//
// 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
//
// XPV ...
//
pvInputs.Default();
//
pvInputs.scMethod = scMethod;
pvInputs.scPeriod = scPeriod;
pvInputs.mcMethod = mcMethod;
pvInputs.mcPeriod = mcPeriod;
pvInputs.lcMethod = lcMethod;
pvInputs.lcPeriod = lcPeriod;
pvInputs.hcMethod = hcMethod;
pvInputs.hcPeriod = hcPeriod;
//
pvInputs.showPeaksAndVales = true;
pvInputs.showLevels = false;
pvInputs.showConsolidations = false;
pvInputs.showFibo1Levels = false;
pvInputs.showFibo2Levels = false;
pvInputs.showFibo3Levels = true;
pvInputs.showFibo4Levels = false;
pvInputs.showFibo5Levels = false;
//
pvHelper = new XSCXPVHelper();
pvHelper.Init(
symbol,
period,
pvInputs //
);
//
// XCHVWAP ...
//
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(
symbol,
period,
chvwapInputs //
);
}
/**
* Detect Direction of VWAP ...
*
* @return ( bool )
*/
ENUM_X_DIRECTION DetectVWAPDirection()
{
//
ENUM_X_DIRECTION result = X_DIRECTION_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();
//
// Reading Indicator's Conditions ...
XCHVWAPConditions chvwapConditions;
chvwapHelper.GetConditions(
chvwapConditions,
cIndex,
loopback //
);
//
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 isBullishDirection =
isBullishState &&
isBullishOrdered;
//
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 isBearishDirection =
isBearishState &&
isBearishOrdered;
//
if (isBullishDirection &&
!isBearishDirection)
{
result = X_DIRECTION_BULLISH;
}
else if (
isBearishDirection &&
!isBullishDirection)
{
result = X_DIRECTION_BEARISH;
}
//
return result;
}
/**
* Detect XPV POIs ...
*
* @param hhs: Double array ...
* @param lls: Double array ...
*
* @return ( int )
*/
int DetectPVPOIs(
double &values[] //
)
{
//
int result = 0;
//
Clean(values);
//
int zIndex = 0;
int cIndex = zIndex + 1;
int pIndex = cIndex + 1;
//
int requiredCount = 10;
long chartID = ChartIdentification();
int subWindow = SubWindowIdentification();
//
int loopback = 300;
int dest = cIndex + loopback;
string symbol = GetSymbol();
datetime cTime = TimeCurrent();
ENUM_TIMEFRAMES period = GetPeriod();
//
XOHCL cBar;
bool isInited = cBar.Init(
symbol,
period,
cIndex //
);
if (!isInited)
{
return result;
}
//
XPVConditions pvConditions;
pvHelper.GetConditions(
pvConditions,
cIndex,
loopback //
);
//
// Find POI ...
for (int i = 0; i < loopback; i++)
{
//
int iCount = 0;
double iValue = pvConditions.sCHHs[i];
//
// Peaks ...
for (int j = 0; j < loopback; j++)
{
//
double jValue = pvConditions.peaks[j];
//
if (jValue == iValue)
{
iCount++;
}
}
//
// Values ...
for (int j = 0; j < loopback; j++)
{
//
double jValue = pvConditions.vales[j];
//
if (jValue == iValue)
{
iCount++;
}
}
//
// Resistance ...
for (int j = 0; j < loopback; j++)
{
//
double jValue = pvConditions.resistances[j];
//
if (jValue == iValue)
{
iCount++;
}
}
//
// Support ...
for (int j = 0; j < loopback; j++)
{
//
double jValue = pvConditions.supports[j];
//
if (jValue == iValue)
{
iCount++;
}
}
//
// Short Cycle Highest Highs ...
for (int j = i + 1; j < loopback; j++)
{
//
double jValue = pvConditions.sCHHs[j];
//
if (jValue == iValue)
{
iCount++;
}
}
//
// Short Cycle Lowest Low ...
for (int j = 0; j < loopback; j++)
{
//
double jValue = pvConditions.sCLLs[j];
//
if (jValue == iValue)
{
iCount++;
}
}
//
// Medium Cycle Highest Highs ...
for (int j = 0; j < loopback; j++)
{
//
double jValue = pvConditions.mCHHs[j];
//
if (jValue == iValue)
{
iCount++;
}
}
//
// Medium Cycle Lowest Low ...
for (int j = 0; j < loopback; j++)
{
//
double jValue = pvConditions.mCLLs[j];
//
if (jValue == iValue)
{
iCount++;
}
}
//
// Long Cycle Highest Highs ...
for (int j = 0; j < loopback; j++)
{
//
double jValue = pvConditions.lCHHs[j];
//
if (jValue == iValue)
{
iCount++;
}
}
//
// Long Cycle Lowest Low ...
for (int j = 0; j < loopback; j++)
{
//
double jValue = pvConditions.lCLLs[j];
//
if (jValue == iValue)
{
iCount++;
}
}
//
// Hind Cycle Highest Highs ...
for (int j = 0; j < loopback; j++)
{
//
double jValue = pvConditions.hCHHs[j];
//
if (jValue == iValue)
{
iCount++;
}
}
//
// Hind Cycle Lowest Low ...
for (int j = 0; j < loopback; j++)
{
//
double jValue = pvConditions.hCLLs[j];
//
if (jValue == iValue)
{
iCount++;
}
}
//
if (iCount >= requiredCount)
{
//
AddIfNotExists(
iValue,
values //
);
}
}
//
result = ArraySize(values);
//
bool drawPOIs = true;
int width = 1;
ENUM_LINE_STYLE lineStyle = STYLE_DOT;
color clrResistance = clrOrange;
color clrSupport = clrTeal;
//
if (drawPOIs &&
IsValidSize(result))
{
//
for (int i = 0; i < result; i++)
{
//
double iValue = values[i];
//
datetime time1 = (datetime)((int)cBar.time - (2 * PeriodSeconds(cBar.period)));
datetime time2 = (datetime)((int)cBar.time + (2 * PeriodSeconds(cBar.period)));
//
string hash = "POI_" + ToString(iValue) + "_" + ToString(time1) + ToString(time2);
hash = ToMD5(hash);
//
string iName = "POI_" + ToString(iValue) + "_" + hash;
//
CChartObjectTrend *iObj;
iObj = new CChartObjectTrend();
bool isCreated = iObj.Create(
chartID,
iName,
subWindow,
time1,
iValue,
time2,
iValue //
);
if (isCreated)
{
//
iObj.Width(width);
iObj.Style(lineStyle);
//
if (iValue > cBar.close)
{
iObj.Color(clrResistance);
}
else if (iValue < cBar.close)
{
iObj.Color(clrSupport);
}
//
mDrawnObjects.Add(iObj);
}
}
}
//
return result;
}
//
};
//