1030 lines
19 KiB
Plaintext
1030 lines
19 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Tools Library
|
|
// --------------------------------------
|
|
// Name: XToolsLib
|
|
// Description: provide all commonly used Tools ...
|
|
//
|
|
//
|
|
// 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-saherelm.draw.lib.mq5"
|
|
#include "../Libraries/x-saherelm.common.lib.mq5"
|
|
|
|
//
|
|
// Definitions ...
|
|
|
|
//
|
|
// a Pivot Point ...
|
|
struct XPivot
|
|
{
|
|
//
|
|
string symbol; // Trading Symbol ...
|
|
ENUM_TIMEFRAMES period; // Trading TimeFrame ...
|
|
|
|
//
|
|
double price; // Price ...
|
|
datetime time; // Time ...
|
|
|
|
//
|
|
int breakedAsSupport; // Number of Breaked As Support ...
|
|
int rejectedAsSupport; // Number of Rejected As Support ...
|
|
|
|
//
|
|
int breakedAsResistance; // Number of Breaked As Resistance ...
|
|
int rejectedAsResistance; // Number of Rejected As Resistance ...
|
|
|
|
//
|
|
bool isSupport;
|
|
bool isResistance;
|
|
|
|
//
|
|
int _lastCalculatedBar;
|
|
int _loopbackForSupportAndResistance; // Number of LoopBacks for Support or Resistance ...
|
|
|
|
//
|
|
// Constructor ...
|
|
XPivot()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Initialization ...
|
|
bool Init(
|
|
string _symbol,
|
|
ENUM_TIMEFRAMES _period,
|
|
double _price,
|
|
int _supResVerifications = 21 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
_price > 0 &&
|
|
IsValid(_symbol) &&
|
|
IsValid(_period) &&
|
|
IsValidSize(_supResVerifications)
|
|
//
|
|
;
|
|
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
symbol = _symbol;
|
|
period = _period;
|
|
price = _price;
|
|
|
|
//
|
|
_loopbackForSupportAndResistance = _supResVerifications;
|
|
|
|
//
|
|
Calculate();
|
|
|
|
//
|
|
result = IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
// Check Support Rejected ...
|
|
bool IsSupportRejected()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = isSupport;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Initialize Required Bars ...
|
|
|
|
//
|
|
XOHCL cBar;
|
|
result = cBar.Init(
|
|
symbol,
|
|
period,
|
|
1 //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL pBar;
|
|
result = pBar.Init(
|
|
symbol,
|
|
period,
|
|
2 //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
// Check Support Touch or Fake Break ...
|
|
pBar.low < price
|
|
//
|
|
&&
|
|
//
|
|
// Check Rejection ...
|
|
cBar.low > price
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Support Breaked ...
|
|
bool IsSupportBreaked()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = isSupport;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Initialize Required Bars ...
|
|
|
|
//
|
|
XOHCL cBar;
|
|
result = cBar.Init(
|
|
symbol,
|
|
period,
|
|
1 //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL pBar;
|
|
result = pBar.Init(
|
|
symbol,
|
|
period,
|
|
2 //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
// Check Support Breaks ...
|
|
pBar.close < price
|
|
//
|
|
&&
|
|
//
|
|
// Check 50% ...
|
|
(price - pBar.close) > (pBar.GetBody() / 100) * 50
|
|
//
|
|
&&
|
|
//
|
|
// Also Next Bar must Closed Below Support ...
|
|
cBar.high < price
|
|
//
|
|
&&
|
|
//
|
|
cBar.close < price
|
|
//
|
|
&&
|
|
//
|
|
cBar.IsBullish()
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Resistance Rejected ...
|
|
bool IsResistanceRejected()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = isResistance;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Initialize Required Bars ...
|
|
|
|
//
|
|
XOHCL cBar;
|
|
result = cBar.Init(
|
|
symbol,
|
|
period,
|
|
1 //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL pBar;
|
|
result = pBar.Init(
|
|
symbol,
|
|
period,
|
|
2 //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
// Check Resistance Touch or Fake Break ...
|
|
pBar.high > price
|
|
//
|
|
&&
|
|
//
|
|
// Check Rejection ...
|
|
cBar.high < price
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Resistance Breaked ...
|
|
bool IsResistanceBreaked()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = isResistance;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Initialize Required Bars ...
|
|
|
|
//
|
|
XOHCL cBar;
|
|
result = cBar.Init(
|
|
symbol,
|
|
period,
|
|
1 //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL pBar;
|
|
result = pBar.Init(
|
|
symbol,
|
|
period,
|
|
2 //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
// Check Resistance Breaks ...
|
|
pBar.close > price
|
|
//
|
|
&&
|
|
//
|
|
// Check 50% ...
|
|
(pBar.close - price) > (pBar.GetBody() / 100) * 50
|
|
//
|
|
&&
|
|
//
|
|
// Also Next Bar Must Closed Above Resistance ...
|
|
cBar.low > price
|
|
//
|
|
&&
|
|
//
|
|
cBar.close > price
|
|
//
|
|
&&
|
|
//
|
|
cBar.IsBullish()
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Cleanup ...
|
|
void Clean()
|
|
{
|
|
//
|
|
symbol = NULL;
|
|
period = NULL;
|
|
time = NULL;
|
|
|
|
//
|
|
price = 0;
|
|
|
|
//
|
|
breakedAsSupport = 0;
|
|
rejectedAsSupport = 0;
|
|
breakedAsResistance = 0;
|
|
rejectedAsResistance = 0;
|
|
|
|
//
|
|
_lastCalculatedBar = -1;
|
|
|
|
//
|
|
isSupport = false;
|
|
isResistance = false;
|
|
}
|
|
|
|
//
|
|
// Validate Model ...
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(symbol) &&
|
|
IsValid(period) &&
|
|
price > 0
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Required Data ...
|
|
void Calculate(int loopback = 288)
|
|
{
|
|
//
|
|
if (isSupport || isResistance)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int bars = iBars(
|
|
symbol,
|
|
period //
|
|
);
|
|
|
|
//
|
|
// Normalizing Loopback ...
|
|
if (loopback > bars)
|
|
{
|
|
loopback = bars - 2 - _loopbackForSupportAndResistance;
|
|
}
|
|
|
|
//
|
|
// Check Previous Calculation ...
|
|
if (bars == _lastCalculatedBar)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
_lastCalculatedBar = bars;
|
|
|
|
//
|
|
// First Get Current State of Pivot ...
|
|
// Means Use Zero Index ...
|
|
XOHCL pBar;
|
|
bool isInited = pBar.Init(
|
|
symbol,
|
|
period,
|
|
1 //
|
|
);
|
|
if (!isInited)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Retrieve Highest High and Lowest Low of SupRes Loopback ...
|
|
double hhValue = pBar
|
|
.FindHighest(
|
|
_loopbackForSupportAndResistance,
|
|
MODE_HIGH //
|
|
);
|
|
|
|
//
|
|
double llValue = pBar
|
|
.FindLowest(
|
|
_loopbackForSupportAndResistance,
|
|
MODE_LOW //
|
|
);
|
|
|
|
//
|
|
isSupport = llValue > price;
|
|
isResistance = hhValue < price;
|
|
|
|
//
|
|
// Prevent Moving Forward if it isn't Support or Resistance ...
|
|
if (!isSupport && !isResistance)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
time = TimeCurrent();
|
|
|
|
//
|
|
for (int i = 2; i < loopback; i++)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
isInited = iBar.Init(
|
|
symbol,
|
|
period,
|
|
i //
|
|
);
|
|
if (!isInited)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
XOHCL iPBar;
|
|
isInited = iPBar.Init(
|
|
symbol,
|
|
period,
|
|
i + 1 //
|
|
);
|
|
if (!isInited)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
XOHCL iPPBar;
|
|
isInited = iPPBar.Init(
|
|
symbol,
|
|
period,
|
|
i + 2 //
|
|
);
|
|
if (!isInited)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isBreaked = false;
|
|
bool isRejected = false;
|
|
|
|
//
|
|
if (isSupport)
|
|
{
|
|
//
|
|
// Count Support Rejects
|
|
// and Support Breaks ...
|
|
|
|
//
|
|
// Support Rejected ...
|
|
isRejected =
|
|
//
|
|
// Check Support Touch or Fake Break ...
|
|
iPBar.low < price
|
|
//
|
|
&&
|
|
//
|
|
// Check Rejection ...
|
|
iBar.low > price
|
|
//
|
|
;
|
|
if (isRejected)
|
|
{
|
|
rejectedAsSupport++;
|
|
}
|
|
|
|
//
|
|
// Support Breaked ...
|
|
isBreaked =
|
|
//
|
|
// Check Support Breaks ...
|
|
iPBar.close < price
|
|
//
|
|
&&
|
|
//
|
|
// Check 50% ...
|
|
(price - iPBar.close) > (iPBar.GetBody() / 100) * 50
|
|
//
|
|
&&
|
|
//
|
|
// Also Next Bar must Closed Below Support ...
|
|
iBar.high < price
|
|
//
|
|
&&
|
|
//
|
|
iBar.close < price
|
|
//
|
|
&&
|
|
//
|
|
iBar.IsBullish()
|
|
//
|
|
;
|
|
if (isBreaked)
|
|
{
|
|
breakedAsSupport++;
|
|
}
|
|
}
|
|
else if (isResistance)
|
|
{
|
|
//
|
|
// Count Resistance Reject
|
|
// or Resistance Breaks ...
|
|
|
|
//
|
|
// Resistance Rejected ...
|
|
isRejected =
|
|
//
|
|
// Check Resistance Touch or Fake Break ...
|
|
iPBar.high > price
|
|
//
|
|
&&
|
|
//
|
|
// Check Rejection ...
|
|
iBar.high < price
|
|
//
|
|
;
|
|
if (isRejected)
|
|
{
|
|
rejectedAsResistance++;
|
|
}
|
|
|
|
//
|
|
// Resistance Breaked ...
|
|
isBreaked =
|
|
//
|
|
// Check Resistance Breaks ...
|
|
iPBar.close > price
|
|
//
|
|
&&
|
|
//
|
|
// Check 50% ...
|
|
(iPBar.close - price) > (iPBar.GetBody() / 100) * 50
|
|
//
|
|
&&
|
|
//
|
|
// Also Next Bar Must Closed Above Resistance ...
|
|
iBar.low > price
|
|
//
|
|
&&
|
|
//
|
|
iBar.close > price
|
|
//
|
|
&&
|
|
//
|
|
iBar.IsBullish()
|
|
//
|
|
;
|
|
if (isBreaked)
|
|
{
|
|
breakedAsResistance++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
string GetTag() {
|
|
return "XPivot";
|
|
}
|
|
};
|
|
|
|
//
|
|
// a Zone Modeling ...
|
|
|
|
//
|
|
enum ENUM_XZONE_STATE
|
|
{
|
|
XZONE_STATE_INVALID = 0, // Invalid Zone ...
|
|
XZONE_STATE_FULL_SUPPORT = 1, // Full Support (up / down) are Support ...
|
|
XZONE_STATE_FULL_RESISTANCE = 2, // Full Resistance (up / down) are Resistaence ...
|
|
XZONE_STATE_CONSOLIDATE = 3, // Down are Support and Up are Resistance ...
|
|
};
|
|
|
|
//
|
|
struct XZone
|
|
{
|
|
//
|
|
string symbol; // Trading Symbol ...
|
|
ENUM_TIMEFRAMES period; // Trading TimeFrame ...
|
|
|
|
//
|
|
datetime time;
|
|
|
|
//
|
|
XPivot up; // Up pivot ...
|
|
XPivot down; // Down Pivot ...
|
|
|
|
//
|
|
// Constructor ...
|
|
XZone()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Initialize a Zone ...
|
|
bool Init(
|
|
string _symbol,
|
|
ENUM_TIMEFRAMES _period,
|
|
double _upPrice,
|
|
double _downPrice //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(_symbol) &&
|
|
IsValid(_period) &&
|
|
_upPrice > 0 &&
|
|
_downPrice > 0 &&
|
|
_downPrice < _upPrice
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
symbol = _symbol;
|
|
period = _period;
|
|
|
|
//
|
|
result = up.Init(
|
|
symbol,
|
|
period,
|
|
_upPrice //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = down.Init(
|
|
symbol,
|
|
period,
|
|
_downPrice //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsValid();
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
time = TimeCurrent();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
// Check XZone State ...
|
|
ENUM_XZONE_STATE GetState()
|
|
{
|
|
//
|
|
ENUM_XZONE_STATE result = XZONE_STATE_INVALID;
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
up.Calculate();
|
|
down.Calculate();
|
|
|
|
//
|
|
if (up.isSupport && down.isSupport)
|
|
{
|
|
result = XZONE_STATE_FULL_SUPPORT;
|
|
}
|
|
else if (up.isResistance && down.isResistance)
|
|
{
|
|
result = XZONE_STATE_FULL_RESISTANCE;
|
|
}
|
|
else if (up.isSupport && down.isResistance)
|
|
{
|
|
result = XZONE_STATE_CONSOLIDATE;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Zone Rejected ...
|
|
|
|
//
|
|
// Check Zone Breaked ...
|
|
|
|
//
|
|
// Cleanup ...
|
|
void Clean()
|
|
{
|
|
//
|
|
symbol = NULL;
|
|
period = NULL;
|
|
time = NULL;
|
|
|
|
//
|
|
up.Clean();
|
|
down.Clean();
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(symbol) &&
|
|
IsValid(period) &&
|
|
up.IsValid() &&
|
|
down.IsValid()
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
};
|
|
|
|
//
|
|
// a Range Box Model ...
|
|
struct XRBox
|
|
{
|
|
//
|
|
string symbol;
|
|
ENUM_TIMEFRAMES period;
|
|
|
|
//
|
|
datetime time;
|
|
datetime expiration;
|
|
|
|
//
|
|
XZone up; // Up Zone ...
|
|
XZone down; // Down Zone ...
|
|
|
|
//
|
|
// Constructor ...
|
|
XRBox()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Initialization ...
|
|
bool Init(
|
|
string _symbol,
|
|
ENUM_TIMEFRAMES _period,
|
|
double _upZoneUpperPrice,
|
|
double _upZoneLowerPrice,
|
|
double _downZoneUpperPrice,
|
|
double _downZoneLowerPrice,
|
|
datetime _expiration = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(_symbol) &&
|
|
IsValid(_period) &&
|
|
_upZoneUpperPrice > 0 &&
|
|
_upZoneLowerPrice > 0 &&
|
|
_upZoneLowerPrice < _upZoneUpperPrice &&
|
|
_downZoneUpperPrice > 0 &&
|
|
_downZoneLowerPrice > 0 &&
|
|
_downZoneLowerPrice < _downZoneUpperPrice
|
|
//
|
|
;
|
|
//
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsValid();
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
time = TimeCurrent();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
// Cleanup ...
|
|
void Clean()
|
|
{
|
|
//
|
|
time = NULL;
|
|
symbol = NULL;
|
|
period = NULL;
|
|
expiration = NULL;
|
|
|
|
//
|
|
up.Clean();
|
|
down.Clean();
|
|
}
|
|
|
|
//
|
|
// Validation ...
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(symbol) &&
|
|
IsValid(period) &&
|
|
up.IsValid() &&
|
|
down.IsValid()
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
};
|
|
|
|
//
|
|
// Detect Trends ...
|
|
struct XTrendDetector
|
|
{
|
|
//
|
|
string symbol;
|
|
ENUM_TIMEFRAMES period;
|
|
|
|
//
|
|
double higherHighs[];
|
|
datetime higherHighTimes[];
|
|
|
|
//
|
|
double higherLows[];
|
|
datetime higherLowTimes[];
|
|
|
|
//
|
|
double lowerHighs[];
|
|
datetime lowerHighTimes[];
|
|
|
|
//
|
|
double lowerLows[];
|
|
datetime lowerLowTimes[];
|
|
|
|
//
|
|
int _numberOfPivots;
|
|
int _pivotShoulders;
|
|
|
|
//
|
|
// Constructor ...
|
|
XTrendDetector()
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
// Cleanup ...
|
|
void Clean()
|
|
{
|
|
//
|
|
symbol = NULL;
|
|
period = NULL;
|
|
|
|
//
|
|
_numberOfPivots = 0;
|
|
_pivotShoulders = 0;
|
|
|
|
//
|
|
Clean(higherHighs);
|
|
Clean(higherHighTimes);
|
|
|
|
//
|
|
Clean(higherLows);
|
|
Clean(higherLowTimes);
|
|
|
|
//
|
|
Clean(lowerHighs);
|
|
Clean(lowerHighTimes);
|
|
|
|
//
|
|
Clean(lowerLows);
|
|
Clean(lowerLowTimes);
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(symbol) &&
|
|
IsValid(period)
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
};
|