transfer important area and its related methods and Properties to XStrategy class ...
This commit is contained in:
@@ -28,15 +28,6 @@
|
||||
//
|
||||
// Definitions ...
|
||||
|
||||
//
|
||||
enum ENUM_X_SIGNALLING_DIRECTION
|
||||
{
|
||||
X_SIGNALLING_NONE = 0,
|
||||
X_SIGNALLING_BOTH_DIRECTIONS = 1,
|
||||
X_SIGNALLING_TREND_DIRECTION = 2,
|
||||
X_SIGNALIING_TREND_REVERSAL_DIRECTION = 3
|
||||
};
|
||||
|
||||
//
|
||||
class XSCBaseStrategy : public XSCBaseAlert
|
||||
{
|
||||
@@ -48,6 +39,7 @@ public:
|
||||
void XSCBaseStrategy(
|
||||
string _symbol, // Trading Symbol
|
||||
ENUM_TIMEFRAMES _period, // Trading TimeFrame
|
||||
ENUM_TIMEFRAMES _analizePeriod, // Important Area Detect Time Frame
|
||||
double _volume, // Voluem
|
||||
double _r2r, // Risk/Reward Ratio
|
||||
int _slippage, // Trader Slippage
|
||||
@@ -79,6 +71,7 @@ public:
|
||||
mAllowLong = _allowLong;
|
||||
mAllowShort = _allowShort;
|
||||
mMagicNumber = _magicNumber;
|
||||
mAnalizePeriod = _analizePeriod;
|
||||
mUseTPSLAsPoint = _useTPSLAsPoint;
|
||||
mMaxAllowedLongs = _maxAllowedLongs;
|
||||
mMaxAllowedShorts = _maxAllowedShorts;
|
||||
@@ -396,6 +389,30 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
ENUM_TIMEFRAMES AnalizePeriod()
|
||||
{
|
||||
return mAnalizePeriod;
|
||||
}
|
||||
|
||||
//
|
||||
void AnalizePeriod(ENUM_TIMEFRAMES value)
|
||||
{
|
||||
mAnalizePeriod = value;
|
||||
}
|
||||
|
||||
//
|
||||
bool DrawImportantAreas()
|
||||
{
|
||||
return mDrawImportantAreas;
|
||||
}
|
||||
|
||||
//
|
||||
void DrawImportantAreas(bool value)
|
||||
{
|
||||
mDrawImportantAreas = value;
|
||||
}
|
||||
|
||||
//
|
||||
// Virtual Methods ...
|
||||
|
||||
@@ -749,6 +766,672 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
ENUM_TIMEFRAMES mAnalizePeriod; // Important Area Detect Time Frame
|
||||
bool mDrawImportantAreas; // Draw Important Areas where Founded in Analyzing Time Frame
|
||||
|
||||
//
|
||||
XOHCL support;
|
||||
XOHCL resistance;
|
||||
XOHCL bullishOB;
|
||||
XOHCL bearishOB;
|
||||
|
||||
//
|
||||
double bullishFVGUpper;
|
||||
double bullishFVGLower;
|
||||
XOHCL bullishFVG;
|
||||
|
||||
//
|
||||
double bearishFVGUpper;
|
||||
double bearishFVGLower;
|
||||
XOHCL bearishFVG;
|
||||
|
||||
//
|
||||
XOHCL bullishTrendSwingHighs[];
|
||||
XOHCL bullishTrendSwingLows[];
|
||||
XOHCL bullishTrend;
|
||||
|
||||
//
|
||||
XOHCL bearishTrendSwingHighs[];
|
||||
XOHCL bearishTrendSwingLows[];
|
||||
XOHCL bearishTrend;
|
||||
|
||||
//
|
||||
void DetectImportantAreas()
|
||||
{
|
||||
//
|
||||
int zIndex = 0;
|
||||
int cIndex = zIndex + 1;
|
||||
|
||||
//
|
||||
// Last Bar ...
|
||||
XOHCL cBar;
|
||||
bool result = cBar.Init(
|
||||
mSymbol,
|
||||
mPeriod,
|
||||
cIndex //
|
||||
);
|
||||
if (!result)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Analyzing Bar ...
|
||||
XOHCL aBar;
|
||||
if (IsValid(mAnalizePeriod))
|
||||
{
|
||||
//
|
||||
result = aBar.Init(
|
||||
mSymbol,
|
||||
mAnalizePeriod,
|
||||
cIndex //
|
||||
);
|
||||
|
||||
//
|
||||
if (!result)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aBar = cBar;
|
||||
}
|
||||
|
||||
//
|
||||
// Support nad Resistance ...
|
||||
|
||||
//
|
||||
// Check Support Exists or Find ...
|
||||
bool hasSupport = support.IsValid();
|
||||
if (!hasSupport)
|
||||
{
|
||||
//
|
||||
hasSupport =
|
||||
//
|
||||
aBar.HasSupport(support)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
if (hasSupport)
|
||||
{
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawSupport(
|
||||
support,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
supportTime = aBar.time;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check Resistance Exists or Find ...
|
||||
bool hasResistance = resistance.IsValid();
|
||||
if (!hasResistance)
|
||||
{
|
||||
//
|
||||
hasResistance =
|
||||
//
|
||||
aBar.HasResistance(resistance)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
if (hasResistance)
|
||||
{
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawResistance(
|
||||
resistance,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
resistanceTime = aBar.time;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Order Blocks ...
|
||||
|
||||
//
|
||||
bool hasBullishOB = bullishOB.IsValid();
|
||||
if (!hasBullishOB)
|
||||
{
|
||||
//
|
||||
hasBullishOB =
|
||||
//
|
||||
aBar.HasBullishOrderBlock(bullishOB)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
if (hasBullishOB)
|
||||
{
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawBullishOrderBlock(
|
||||
bullishOB,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
bullishOBTime = aBar.time;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
bool hasBearishOB = bearishOB.IsValid();
|
||||
if (!hasBearishOB)
|
||||
{
|
||||
//
|
||||
hasBearishOB =
|
||||
//
|
||||
aBar.HasBearishOrderBlock(bearishOB)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
if (hasBearishOB)
|
||||
{
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawBearishOrderBlock(
|
||||
bearishOB,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
bearishOBTime = aBar.time;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// FVG ...
|
||||
|
||||
//
|
||||
bool hasBullishFVG = bullishFVG.IsValid();
|
||||
if (!hasBullishFVG)
|
||||
{
|
||||
//
|
||||
hasBullishFVG =
|
||||
//
|
||||
aBar.HasBullishFVG(
|
||||
bullishFVGUpper,
|
||||
bullishFVGLower //
|
||||
)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
if (hasBullishFVG)
|
||||
{
|
||||
//
|
||||
bullishFVG = aBar;
|
||||
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawBullishFVG(
|
||||
bullishFVG,
|
||||
bullishFVGUpper,
|
||||
bullishFVGLower,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
bullishFVGTime = aBar.time;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
bool hasBearishFVG = bearishFVG.IsValid();
|
||||
if (!hasBearishFVG)
|
||||
{
|
||||
//
|
||||
hasBearishFVG =
|
||||
//
|
||||
aBar.HasBearishFVG(
|
||||
bearishFVGUpper,
|
||||
bearishFVGLower //
|
||||
)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
if (hasBearishFVG)
|
||||
{
|
||||
//
|
||||
bearishFVG = aBar;
|
||||
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawBearishFVG(
|
||||
bearishFVG,
|
||||
bearishFVGUpper,
|
||||
bearishFVGLower,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
bearishFVGTime = aBar.time;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TREND ...
|
||||
|
||||
//
|
||||
bool hasBullishTrend = bullishTrend.IsValid();
|
||||
if (!hasBullishTrend)
|
||||
{
|
||||
//
|
||||
hasBullishTrend = aBar.HasBullishTrend(
|
||||
bullishTrendSwingHighs,
|
||||
bullishTrendSwingLows,
|
||||
false //
|
||||
);
|
||||
|
||||
//
|
||||
if (hasBullishTrend)
|
||||
{
|
||||
//
|
||||
bullishTrend = aBar;
|
||||
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawBullishTrend(
|
||||
bullishTrend,
|
||||
bullishTrendSwingHighs,
|
||||
bullishTrendSwingLows,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
bool hasBearishTrend = bearishTrend.IsValid();
|
||||
if (!hasBearishTrend)
|
||||
{
|
||||
//
|
||||
hasBearishTrend = aBar.HasBearishTrend(
|
||||
bearishTrendSwingHighs,
|
||||
bearishTrendSwingLows,
|
||||
false //
|
||||
);
|
||||
|
||||
//
|
||||
if (hasBearishTrend)
|
||||
{
|
||||
//
|
||||
bearishTrend = aBar;
|
||||
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawBearishTrend(
|
||||
bearishTrend,
|
||||
bearishTrendSwingHighs,
|
||||
bearishTrendSwingLows,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
//
|
||||
void DestroyImportantAreas()
|
||||
{
|
||||
//
|
||||
bool hasSupport = support.IsValid();
|
||||
if (hasSupport)
|
||||
{
|
||||
//
|
||||
supportTime = NULL;
|
||||
isSupportTested = false;
|
||||
RemoveSupport(support);
|
||||
support.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
bool hasResistance = resistance.IsValid();
|
||||
if (hasResistance)
|
||||
{
|
||||
//
|
||||
resistanceTime = NULL;
|
||||
isResistanceTested = false;
|
||||
RemoveResistance(resistance);
|
||||
resistance.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
bool hasBullishOB = bullishOB.IsValid();
|
||||
if (hasBullishOB)
|
||||
{
|
||||
//
|
||||
bullishOBTime = NULL;
|
||||
RemoveBullishOrderBlock(bullishOB);
|
||||
bullishOB.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
bool hasBearishOB = bearishOB.IsValid();
|
||||
if (hasBearishOB)
|
||||
{
|
||||
//
|
||||
bearishOBTime = NULL;
|
||||
RemoveBearishOrderBlock(bearishOB);
|
||||
bearishOB.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
bool hasBullishFVG = bullishFVG.IsValid();
|
||||
if (hasBullishFVG)
|
||||
{
|
||||
//
|
||||
bullishFVGUpper = 0;
|
||||
bullishFVGLower = 0;
|
||||
bullishFVGTime = NULL;
|
||||
RemoveBullishFVG(bullishFVG);
|
||||
bullishFVG.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
bool hasBearishFVG = bearishFVG.IsValid();
|
||||
if (hasBearishFVG)
|
||||
{
|
||||
//
|
||||
bearishFVGUpper = 0;
|
||||
bearishFVGLower = 0;
|
||||
bearishFVGTime = NULL;
|
||||
RemoveBullishFVG(bearishFVG);
|
||||
bearishFVG.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
bool hasBullishTrend = bullishTrend.IsValid();
|
||||
if (hasBullishTrend)
|
||||
{
|
||||
//
|
||||
RemoveBullishTrend(bullishTrend);
|
||||
bullishTrend.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
bool hasBearishTrend = bearishTrend.IsValid();
|
||||
if (hasBearishTrend)
|
||||
{
|
||||
//
|
||||
RemoveBearishTrend(bearishTrend);
|
||||
bearishTrend.Clean();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
void CheckImportantAreasValidation()
|
||||
{
|
||||
//
|
||||
CheckSupportValidation();
|
||||
CheckResistanceValidation();
|
||||
|
||||
//
|
||||
CheckBullishOBValidation();
|
||||
CheckBearishOBValidation();
|
||||
|
||||
//
|
||||
CheckBullishFVGValidation();
|
||||
CheckBearishFVgValidation();
|
||||
|
||||
//
|
||||
CheckBullishTrendValidation();
|
||||
CheckBearishTrendValidation();
|
||||
}
|
||||
|
||||
//
|
||||
bool isSupportTested;
|
||||
datetime supportTime;
|
||||
void CheckSupportValidation()
|
||||
{
|
||||
//
|
||||
if (!isSupportTested)
|
||||
{
|
||||
//
|
||||
if (support.IsValid() && IsValid(supportTime))
|
||||
{
|
||||
//
|
||||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(supportTime))) / PeriodSeconds(mPeriod));
|
||||
if (age >= 50)
|
||||
{
|
||||
//
|
||||
isSupportTested = false;
|
||||
supportTime = NULL;
|
||||
RemoveSupport(support);
|
||||
support.Clean();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
XOHCL cBar;
|
||||
bool isInited = cBar.Init(
|
||||
mSymbol,
|
||||
mPeriod,
|
||||
1 //
|
||||
);
|
||||
if (!isInited)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
double points = GetPoints(mSymbol);
|
||||
|
||||
//
|
||||
// Find Price Distance ...
|
||||
double highDiff = MathAbs(cBar.high - support.high);
|
||||
double lowDiff = MathAbs(cBar.low - support.high);
|
||||
|
||||
//
|
||||
bool isBreaked = MathMax(highDiff, lowDiff) >= 100 * points;
|
||||
if (!isBreaked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
isSupportTested = false;
|
||||
RemoveSupport(support);
|
||||
supportTime = NULL;
|
||||
support.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
bool isResistanceTested;
|
||||
datetime resistanceTime;
|
||||
void CheckResistanceValidation()
|
||||
{
|
||||
//
|
||||
if (!isResistanceTested)
|
||||
{
|
||||
//
|
||||
if (resistance.IsValid() && IsValid(resistanceTime))
|
||||
{
|
||||
//
|
||||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(resistanceTime))) / PeriodSeconds(mPeriod));
|
||||
if (age >= 50)
|
||||
{
|
||||
//
|
||||
isResistanceTested = false;
|
||||
resistanceTime = NULL;
|
||||
RemoveResistance(resistance);
|
||||
resistance.Clean();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
XOHCL cBar;
|
||||
bool isInited = cBar.Init(
|
||||
mSymbol,
|
||||
mPeriod,
|
||||
1 //
|
||||
);
|
||||
if (!isInited)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
double points = GetPoints(mSymbol);
|
||||
|
||||
//
|
||||
// Find Price Distance ...
|
||||
double highDiff = MathAbs(cBar.high - resistance.low);
|
||||
double lowDiff = MathAbs(cBar.low - resistance.low);
|
||||
|
||||
//
|
||||
bool isBreaked = MathMax(highDiff, lowDiff) >= 100 * points;
|
||||
if (!isBreaked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
isResistanceTested = false;
|
||||
RemoveResistance(resistance);
|
||||
resistanceTime = NULL;
|
||||
resistance.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
datetime bullishOBTime;
|
||||
void CheckBullishOBValidation()
|
||||
{
|
||||
//
|
||||
if (!IsValid(bullishOBTime))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(bullishOBTime))) / PeriodSeconds(mPeriod));
|
||||
if (age >= 50)
|
||||
{
|
||||
//
|
||||
bullishOBTime = NULL;
|
||||
RemoveBullishOrderBlock(bullishOB);
|
||||
bullishOB.Clean();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
datetime bearishOBTime;
|
||||
void CheckBearishOBValidation()
|
||||
{
|
||||
//
|
||||
if (!IsValid(bearishOBTime))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(bearishOBTime))) / PeriodSeconds(mPeriod));
|
||||
if (age >= 50)
|
||||
{
|
||||
//
|
||||
bearishOBTime = NULL;
|
||||
RemoveBearishOrderBlock(bearishOB);
|
||||
bearishOB.Clean();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
datetime bullishFVGTime;
|
||||
void CheckBullishFVGValidation()
|
||||
{
|
||||
//
|
||||
if (!IsValid(bullishFVGTime))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(bullishFVGTime))) / PeriodSeconds(mPeriod));
|
||||
if (age >= 50)
|
||||
{
|
||||
//
|
||||
bullishFVGTime = NULL;
|
||||
RemoveBullishFVG(bullishFVG);
|
||||
bullishFVG.Clean();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
datetime bearishFVGTime;
|
||||
void CheckBearishFVgValidation()
|
||||
{
|
||||
//
|
||||
if (!IsValid(bearishFVGTime))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(bearishFVGTime))) / PeriodSeconds(mPeriod));
|
||||
if (age >= 50)
|
||||
{
|
||||
//
|
||||
bearishFVGTime = NULL;
|
||||
RemoveBearishFVG(bearishFVG);
|
||||
bearishFVG.Clean();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
void CheckBullishTrendValidation()
|
||||
{
|
||||
//
|
||||
// TODO: Complete this ...
|
||||
}
|
||||
|
||||
//
|
||||
void CheckBearishTrendValidation()
|
||||
{
|
||||
//
|
||||
// TODO: Complete this ...
|
||||
}
|
||||
|
||||
//
|
||||
// Private ...
|
||||
private:
|
||||
|
||||
@@ -307,12 +307,12 @@ bool InitialEA()
|
||||
eaSlippage,
|
||||
eaMagicNumber,
|
||||
true, // Ignore Signal Execution
|
||||
true, // Use TP SL Point
|
||||
false, // Use TP SL Point
|
||||
false, // Use Max
|
||||
eaTPPoint, // TP
|
||||
eaSLPoint, // SL
|
||||
eaIgnoreTP,
|
||||
true, // eaIgnoreSL,
|
||||
false, // eaIgnoreSL,
|
||||
eaAllowLong,
|
||||
eaAllowShort,
|
||||
eaMaxAllowedLongs, // Max Longs
|
||||
@@ -447,6 +447,23 @@ void HandleTradeState()
|
||||
// Analyzing ...
|
||||
void OnSignalRecieved(XSignal &signal)
|
||||
{
|
||||
//
|
||||
if (!signal.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
bool isLong = IsLong(signal.type);
|
||||
|
||||
//
|
||||
// Check Allow Trade Type ...
|
||||
if ((isLong && !eaAllowLong) ||
|
||||
(!isLong && !eaAllowShort))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Max Allowed ...
|
||||
if (eaMaxAllowedLongs > 0 || eaMaxAllowedShorts > 0)
|
||||
@@ -480,8 +497,12 @@ void OnSignalRecieved(XSignal &signal)
|
||||
int shortsCount = ArraySize(shorts);
|
||||
|
||||
//
|
||||
if ((eaMaxAllowedLongs > 0 && longsCount >= eaMaxAllowedLongs) ||
|
||||
(eaMaxAllowedShorts > 0 && shortsCount >= eaMaxAllowedShorts))
|
||||
if ((isLong &&
|
||||
eaMaxAllowedLongs > 0 &&
|
||||
longsCount >= eaMaxAllowedLongs) ||
|
||||
(!isLong &&
|
||||
eaMaxAllowedShorts > 0 &&
|
||||
shortsCount >= eaMaxAllowedShorts))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
int _maxAllowedShorts = 0 //
|
||||
) : XSCBaseStrategy(_symbol,
|
||||
_period,
|
||||
_analizePeriod,
|
||||
_volume,
|
||||
_r2r,
|
||||
_slippage,
|
||||
@@ -87,9 +88,6 @@ public:
|
||||
_maxAllowedShorts //
|
||||
)
|
||||
{
|
||||
//
|
||||
mAnalizePeriod = _analizePeriod;
|
||||
|
||||
//
|
||||
SetAlertPrefix(GetTag());
|
||||
|
||||
@@ -114,30 +112,6 @@ public:
|
||||
//
|
||||
// Getter / Setter (s) ...
|
||||
|
||||
//
|
||||
ENUM_TIMEFRAMES AnalizePeriod()
|
||||
{
|
||||
return mAnalizePeriod;
|
||||
}
|
||||
|
||||
//
|
||||
void AnalizePeriod(ENUM_TIMEFRAMES value)
|
||||
{
|
||||
mAnalizePeriod = value;
|
||||
}
|
||||
|
||||
//
|
||||
bool DrawImportantAreas()
|
||||
{
|
||||
return mDrawImportantAreas;
|
||||
}
|
||||
|
||||
//
|
||||
void DrawImportantAreas(bool value)
|
||||
{
|
||||
mDrawImportantAreas = value;
|
||||
}
|
||||
|
||||
//
|
||||
bool EnableXCHCHE()
|
||||
{
|
||||
@@ -521,29 +495,6 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Analyzing Bar ...
|
||||
XOHCL aBar;
|
||||
if (IsValid(mAnalizePeriod))
|
||||
{
|
||||
//
|
||||
result = aBar.Init(
|
||||
mSymbol,
|
||||
mAnalizePeriod,
|
||||
cIndex //
|
||||
);
|
||||
|
||||
//
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aBar = cBar;
|
||||
}
|
||||
|
||||
//
|
||||
// Previous Bar of Last Bar ...
|
||||
XOHCL pBar;
|
||||
@@ -588,272 +539,6 @@ public:
|
||||
MODE_LOW //
|
||||
);
|
||||
|
||||
//
|
||||
// Support nad Resistance ...
|
||||
|
||||
//
|
||||
// Check Support Exists or Find ...
|
||||
bool hasSupport = support.IsValid();
|
||||
if (!hasSupport)
|
||||
{
|
||||
//
|
||||
hasSupport =
|
||||
//
|
||||
aBar.HasSupport(support)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
if (hasSupport)
|
||||
{
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawSupport(
|
||||
support,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
supportTime = aBar.time;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check Resistance Exists or Find ...
|
||||
bool hasResistance = resistance.IsValid();
|
||||
if (!hasResistance)
|
||||
{
|
||||
//
|
||||
hasResistance =
|
||||
//
|
||||
aBar.HasResistance(resistance)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
if (hasResistance)
|
||||
{
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawResistance(
|
||||
resistance,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
resistanceTime = aBar.time;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Order Blocks ...
|
||||
|
||||
//
|
||||
bool hasBullishOB = bullishOB.IsValid();
|
||||
if (!hasBullishOB)
|
||||
{
|
||||
//
|
||||
hasBullishOB =
|
||||
//
|
||||
aBar.HasBullishOrderBlock(bullishOB)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
if (hasBullishOB)
|
||||
{
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawBullishOrderBlock(
|
||||
bullishOB,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
bullishOBTime = aBar.time;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
bool hasBearishOB = bearishOB.IsValid();
|
||||
if (!hasBearishOB)
|
||||
{
|
||||
//
|
||||
hasBearishOB =
|
||||
//
|
||||
aBar.HasBearishOrderBlock(bearishOB)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
if (hasBearishOB)
|
||||
{
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawBearishOrderBlock(
|
||||
bearishOB,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
bearishOBTime = aBar.time;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// FVG ...
|
||||
|
||||
//
|
||||
bool hasBullishFVG = bullishFVG.IsValid();
|
||||
if (!hasBullishFVG)
|
||||
{
|
||||
//
|
||||
hasBullishFVG =
|
||||
//
|
||||
aBar.HasBullishFVG(
|
||||
bullishFVGUpper,
|
||||
bullishFVGLower //
|
||||
)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
if (hasBullishFVG)
|
||||
{
|
||||
//
|
||||
bullishFVG = aBar;
|
||||
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawBullishFVG(
|
||||
bullishFVG,
|
||||
bullishFVGUpper,
|
||||
bullishFVGLower,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
bullishFVGTime = aBar.time;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
bool hasBearishFVG = bearishFVG.IsValid();
|
||||
if (!hasBearishFVG)
|
||||
{
|
||||
//
|
||||
hasBearishFVG =
|
||||
//
|
||||
aBar.HasBearishFVG(
|
||||
bearishFVGUpper,
|
||||
bearishFVGLower //
|
||||
)
|
||||
//
|
||||
;
|
||||
|
||||
//
|
||||
if (hasBearishFVG)
|
||||
{
|
||||
//
|
||||
bearishFVG = aBar;
|
||||
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawBearishFVG(
|
||||
bearishFVG,
|
||||
bearishFVGUpper,
|
||||
bearishFVGLower,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
bearishFVGTime = aBar.time;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TREND ...
|
||||
|
||||
//
|
||||
bool hasBullishTrend = bullishTrend.IsValid();
|
||||
if (!hasBullishTrend)
|
||||
{
|
||||
//
|
||||
hasBullishTrend = aBar.HasBullishTrend(
|
||||
bullishTrendSwingHighs,
|
||||
bullishTrendSwingLows,
|
||||
false //
|
||||
);
|
||||
|
||||
//
|
||||
if (hasBullishTrend)
|
||||
{
|
||||
//
|
||||
bullishTrend = aBar;
|
||||
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawBullishTrend(
|
||||
bullishTrend,
|
||||
bullishTrendSwingHighs,
|
||||
bullishTrendSwingLows,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
bool hasBearishTrend = bearishTrend.IsValid();
|
||||
if (!hasBearishTrend)
|
||||
{
|
||||
//
|
||||
hasBearishTrend = aBar.HasBearishTrend(
|
||||
bearishTrendSwingHighs,
|
||||
bearishTrendSwingLows,
|
||||
false //
|
||||
);
|
||||
|
||||
//
|
||||
if (hasBearishTrend)
|
||||
{
|
||||
//
|
||||
bearishTrend = aBar;
|
||||
|
||||
//
|
||||
if (mDrawImportantAreas)
|
||||
{
|
||||
//
|
||||
DrawBearishTrend(
|
||||
bearishTrend,
|
||||
bearishTrendSwingHighs,
|
||||
bearishTrendSwingLows,
|
||||
ChartID() //
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// For Trend ...
|
||||
XOHCL tmpHSW[];
|
||||
@@ -944,6 +629,9 @@ public:
|
||||
double chcheMaxBearish = chcheHelper.GetBearishMax(cIndex);
|
||||
double chcheMinBearish = chcheHelper.GetBearishMin(cIndex);
|
||||
|
||||
//
|
||||
DetectImportantAreas();
|
||||
|
||||
//
|
||||
int pushers = 0;
|
||||
string signallers[];
|
||||
@@ -1195,13 +883,13 @@ public:
|
||||
//
|
||||
bool chcheHasLong =
|
||||
//
|
||||
hasBullishPower &&
|
||||
cBar.IsBullish() &&
|
||||
hasBullishPattern &&
|
||||
hasBullishPressure &&
|
||||
cBar.low > chcheMinBullish &&
|
||||
chcheConditions.isBullishPowerUp &&
|
||||
chcheConditions.isCStrongBullish
|
||||
// hasBullishPower &&
|
||||
// cBar.IsBullish() &&
|
||||
// hasBullishPattern &&
|
||||
// hasBullishPressure &&
|
||||
// cBar.low > chcheMinBullish &&
|
||||
chcheConditions.isBullishPowerUp // &&
|
||||
// chcheConditions.isCStrongBullish
|
||||
//
|
||||
;
|
||||
|
||||
@@ -1232,13 +920,13 @@ public:
|
||||
//
|
||||
bool chcheHasShort =
|
||||
//
|
||||
hasBearishPower &&
|
||||
cBar.IsBearish() &&
|
||||
hasBearishPattern &&
|
||||
hasBearishPressure &&
|
||||
cBar.high < chcheMaxBearish &&
|
||||
chcheConditions.isBearishPowerUp &&
|
||||
chcheConditions.isCStrongBearish
|
||||
// hasBearishPower &&
|
||||
// cBar.IsBearish() &&
|
||||
// hasBearishPattern &&
|
||||
// hasBearishPressure &&
|
||||
// cBar.high < chcheMaxBearish &&
|
||||
chcheConditions.isBearishPowerUp // &&
|
||||
// chcheConditions.isCStrongBearish
|
||||
//
|
||||
;
|
||||
|
||||
@@ -1269,100 +957,14 @@ public:
|
||||
if (!result)
|
||||
{
|
||||
//
|
||||
CheckSupportValidation();
|
||||
CheckResistanceValidation();
|
||||
|
||||
//
|
||||
CheckBullishOBValidation();
|
||||
CheckBearishOBValidation();
|
||||
|
||||
//
|
||||
CheckBullishFVGValidation();
|
||||
CheckBearishFVgValidation();
|
||||
|
||||
//
|
||||
CheckBullishTrendValidation();
|
||||
CheckBearishTrendValidation();
|
||||
CheckImportantAreasValidation();
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
if (hasSupport)
|
||||
{
|
||||
//
|
||||
supportTime = NULL;
|
||||
isSupportTested = false;
|
||||
RemoveSupport(support);
|
||||
support.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
if (hasResistance)
|
||||
{
|
||||
//
|
||||
resistanceTime = NULL;
|
||||
isResistanceTested = false;
|
||||
RemoveResistance(resistance);
|
||||
resistance.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
if (hasBullishOB)
|
||||
{
|
||||
//
|
||||
bullishOBTime = NULL;
|
||||
RemoveBullishOrderBlock(bullishOB);
|
||||
bullishOB.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
if (hasBearishOB)
|
||||
{
|
||||
//
|
||||
bearishOBTime = NULL;
|
||||
RemoveBearishOrderBlock(bearishOB);
|
||||
bearishOB.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
if (hasBullishFVG)
|
||||
{
|
||||
//
|
||||
bullishFVGUpper = 0;
|
||||
bullishFVGLower = 0;
|
||||
bullishFVGTime = NULL;
|
||||
RemoveBullishFVG(bullishFVG);
|
||||
bullishFVG.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
if (hasBearishFVG)
|
||||
{
|
||||
//
|
||||
bearishFVGUpper = 0;
|
||||
bearishFVGLower = 0;
|
||||
bearishFVGTime = NULL;
|
||||
RemoveBullishFVG(bearishFVG);
|
||||
bearishFVG.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
if (hasBullishTrend)
|
||||
{
|
||||
//
|
||||
RemoveBullishTrend(bullishTrend);
|
||||
bullishTrend.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
if (hasBearishTrend)
|
||||
{
|
||||
//
|
||||
RemoveBearishTrend(bearishTrend);
|
||||
bearishTrend.Clean();
|
||||
}
|
||||
DestroyImportantAreas();
|
||||
|
||||
//
|
||||
// Retrieve Entry Price based on Position Type ...
|
||||
@@ -1411,44 +1013,12 @@ protected:
|
||||
//
|
||||
// Props ...
|
||||
|
||||
//
|
||||
ENUM_TIMEFRAMES mAnalizePeriod; // Important Area Detect Time Frame
|
||||
|
||||
//
|
||||
bool mDrawImportantAreas; // Draw Important Areas where Founded in Analyzing Time Frame
|
||||
|
||||
//
|
||||
bool mEnableXCHM; // Enable XCHM Signaller
|
||||
bool mEnableXCHHK; // Enable XCHHK Signaller
|
||||
bool mEnableXCHSTR; // Enable XCHSTR Signaller
|
||||
bool mEnableXCHCHE; // Enable XCHCHE Signaller
|
||||
|
||||
//
|
||||
XOHCL support;
|
||||
XOHCL resistance;
|
||||
XOHCL bullishOB;
|
||||
XOHCL bearishOB;
|
||||
|
||||
//
|
||||
double bullishFVGUpper;
|
||||
double bullishFVGLower;
|
||||
XOHCL bullishFVG;
|
||||
|
||||
//
|
||||
double bearishFVGUpper;
|
||||
double bearishFVGLower;
|
||||
XOHCL bearishFVG;
|
||||
|
||||
//
|
||||
XOHCL bullishTrendSwingHighs[];
|
||||
XOHCL bullishTrendSwingLows[];
|
||||
XOHCL bullishTrend;
|
||||
|
||||
//
|
||||
XOHCL bearishTrendSwingHighs[];
|
||||
XOHCL bearishTrendSwingLows[];
|
||||
XOHCL bearishTrend;
|
||||
|
||||
//
|
||||
// XPV ...
|
||||
XPVInputs pvInputs;
|
||||
@@ -1485,9 +1055,6 @@ private:
|
||||
// Configurations for required Indicators ...
|
||||
void PrepareRequirements()
|
||||
{
|
||||
//
|
||||
mDrawImportantAreas = false;
|
||||
|
||||
//
|
||||
mEnableXCHM = true;
|
||||
mEnableXCHHK = true;
|
||||
@@ -1698,300 +1265,6 @@ private:
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
bool isSupportTested;
|
||||
datetime supportTime;
|
||||
void CheckSupportValidation()
|
||||
{
|
||||
//
|
||||
if (!isSupportTested)
|
||||
{
|
||||
//
|
||||
if (support.IsValid() && IsValid(supportTime))
|
||||
{
|
||||
//
|
||||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(supportTime))) / PeriodSeconds(mPeriod));
|
||||
if (age >= 50)
|
||||
{
|
||||
//
|
||||
isSupportTested = false;
|
||||
supportTime = NULL;
|
||||
RemoveSupport(support);
|
||||
support.Clean();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
XOHCL cBar;
|
||||
bool isInited = cBar.Init(
|
||||
mSymbol,
|
||||
mPeriod,
|
||||
1 //
|
||||
);
|
||||
if (!isInited)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
double points = GetPoints(mSymbol);
|
||||
|
||||
//
|
||||
// Find Price Distance ...
|
||||
double highDiff = MathAbs(cBar.high - support.high);
|
||||
double lowDiff = MathAbs(cBar.low - support.high);
|
||||
|
||||
//
|
||||
bool isBreaked = MathMax(highDiff, lowDiff) >= 100 * points;
|
||||
if (!isBreaked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
isSupportTested = false;
|
||||
RemoveSupport(support);
|
||||
supportTime = NULL;
|
||||
support.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
bool isResistanceTested;
|
||||
datetime resistanceTime;
|
||||
void CheckResistanceValidation()
|
||||
{
|
||||
//
|
||||
if (!isResistanceTested)
|
||||
{
|
||||
//
|
||||
if (resistance.IsValid() && IsValid(resistanceTime))
|
||||
{
|
||||
//
|
||||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(resistanceTime))) / PeriodSeconds(mPeriod));
|
||||
if (age >= 50)
|
||||
{
|
||||
//
|
||||
isResistanceTested = false;
|
||||
resistanceTime = NULL;
|
||||
RemoveResistance(resistance);
|
||||
resistance.Clean();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
XOHCL cBar;
|
||||
bool isInited = cBar.Init(
|
||||
mSymbol,
|
||||
mPeriod,
|
||||
1 //
|
||||
);
|
||||
if (!isInited)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
double points = GetPoints(mSymbol);
|
||||
|
||||
//
|
||||
// Find Price Distance ...
|
||||
double highDiff = MathAbs(cBar.high - resistance.low);
|
||||
double lowDiff = MathAbs(cBar.low - resistance.low);
|
||||
|
||||
//
|
||||
bool isBreaked = MathMax(highDiff, lowDiff) >= 100 * points;
|
||||
if (!isBreaked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
isResistanceTested = false;
|
||||
RemoveResistance(resistance);
|
||||
resistanceTime = NULL;
|
||||
resistance.Clean();
|
||||
}
|
||||
|
||||
//
|
||||
datetime bullishOBTime;
|
||||
void CheckBullishOBValidation()
|
||||
{
|
||||
//
|
||||
if (!IsValid(bullishOBTime))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(bullishOBTime))) / PeriodSeconds(mPeriod));
|
||||
if (age >= 50)
|
||||
{
|
||||
//
|
||||
bullishOBTime = NULL;
|
||||
RemoveBullishOrderBlock(bullishOB);
|
||||
bullishOB.Clean();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
datetime bearishOBTime;
|
||||
void CheckBearishOBValidation()
|
||||
{
|
||||
//
|
||||
if (!IsValid(bearishOBTime))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(bearishOBTime))) / PeriodSeconds(mPeriod));
|
||||
if (age >= 50)
|
||||
{
|
||||
//
|
||||
bearishOBTime = NULL;
|
||||
RemoveBearishOrderBlock(bearishOB);
|
||||
bearishOB.Clean();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
datetime bullishFVGTime;
|
||||
void CheckBullishFVGValidation()
|
||||
{
|
||||
//
|
||||
if (!IsValid(bullishFVGTime))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(bullishFVGTime))) / PeriodSeconds(mPeriod));
|
||||
if (age >= 50)
|
||||
{
|
||||
//
|
||||
bullishFVGTime = NULL;
|
||||
RemoveBullishFVG(bullishFVG);
|
||||
bullishFVG.Clean();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
datetime bearishFVGTime;
|
||||
void CheckBearishFVgValidation()
|
||||
{
|
||||
//
|
||||
if (!IsValid(bearishFVGTime))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
int age = (int)(((int)(TimeToSeconds(TimeCurrent()) - TimeToSeconds(bearishFVGTime))) / PeriodSeconds(mPeriod));
|
||||
if (age >= 50)
|
||||
{
|
||||
//
|
||||
bearishFVGTime = NULL;
|
||||
RemoveBearishFVG(bearishFVG);
|
||||
bearishFVG.Clean();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
void CheckBullishTrendValidation()
|
||||
{
|
||||
//
|
||||
// TODO: Complete this ...
|
||||
}
|
||||
|
||||
//
|
||||
void CheckBearishTrendValidation()
|
||||
{
|
||||
//
|
||||
// TODO: Complete this ...
|
||||
}
|
||||
|
||||
//
|
||||
// XCHE Custom Data ...
|
||||
|
||||
//
|
||||
double cheLastLongExit1;
|
||||
double cheLastLongExit2;
|
||||
datetime cheLastLongExitTime;
|
||||
double GetMaxCHELastLong()
|
||||
{
|
||||
//
|
||||
return MathMax(
|
||||
cheLastLongExit1,
|
||||
cheLastLongExit2 //
|
||||
);
|
||||
}
|
||||
double GetMinCHELastLong()
|
||||
{
|
||||
//
|
||||
return MathMin(
|
||||
cheLastLongExit1,
|
||||
cheLastLongExit2 //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
double cheLastShortExit1;
|
||||
double cheLastShortExit2;
|
||||
datetime cheLastShortExitTime;
|
||||
double GetMaxCHELastShort()
|
||||
{
|
||||
//
|
||||
return MathMax(
|
||||
cheLastShortExit1,
|
||||
cheLastShortExit2 //
|
||||
);
|
||||
}
|
||||
double GetMinCHELastShort()
|
||||
{
|
||||
//
|
||||
return MathMin(
|
||||
cheLastShortExit1,
|
||||
cheLastShortExit2 //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
double GetMaxCHELast()
|
||||
{
|
||||
//
|
||||
return MathMax(
|
||||
GetMaxCHELastLong(),
|
||||
GetMaxCHELastShort() //
|
||||
);
|
||||
}
|
||||
double GetMinCHELast()
|
||||
{
|
||||
//
|
||||
return MathMin(
|
||||
GetMinCHELastLong(),
|
||||
GetMinCHELastShort() //
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
bool HasCheLast()
|
||||
{
|
||||
//
|
||||
bool result = false;
|
||||
|
||||
//
|
||||
result =
|
||||
IsValid(cheLastLongExitTime) ||
|
||||
IsValid(cheLastShortExitTime);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user