1977 lines
38 KiB
Plaintext
1977 lines
38 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;
|
|
datetime supportTime;
|
|
|
|
//
|
|
bool isResistance;
|
|
datetime resistanceTime;
|
|
|
|
//
|
|
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 barIndex = 0,
|
|
int _supResVerificationsStep = 21 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (_supResVerificationsStep < 0)
|
|
{
|
|
_supResVerificationsStep = 21;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
_price > 0 &&
|
|
IsValid(_symbol) &&
|
|
IsValid(_period) &&
|
|
IsValidSize(_supResVerificationsStep)
|
|
//
|
|
;
|
|
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
symbol = _symbol;
|
|
period = _period;
|
|
price = _price;
|
|
|
|
//
|
|
_loopbackForSupportAndResistance = _supResVerificationsStep;
|
|
|
|
//
|
|
Calculate(
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
result = IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Last Support for Market and
|
|
// Initialize Pivot Based On it ...
|
|
bool FindLastSupport(
|
|
string _symbol,
|
|
ENUM_TIMEFRAMES _period,
|
|
int barIndex = 0,
|
|
int _supResVerificationsStep = 21 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (_supResVerificationsStep < 0)
|
|
{
|
|
_supResVerificationsStep = 21;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(_symbol) &&
|
|
IsValid(_period) &&
|
|
IsValidSize(_supResVerificationsStep)
|
|
//
|
|
;
|
|
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Resistance ...
|
|
|
|
//
|
|
// Retrieve Current Bar ...
|
|
XOHCL cBar;
|
|
result = cBar.Init(
|
|
_symbol,
|
|
_period,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Available Bars ...
|
|
|
|
//
|
|
int bars = iBars(
|
|
_symbol,
|
|
_period //
|
|
);
|
|
int maxAllowedBars = bars - 500;
|
|
int currentLength = _supResVerificationsStep;
|
|
|
|
//
|
|
// Find Highest High ...
|
|
for (int i = barIndex; i < maxAllowedBars; i++)
|
|
{
|
|
//
|
|
// Validate and Regenrate Current Length ...
|
|
if (i > 1)
|
|
{
|
|
//
|
|
currentLength = _supResVerificationsStep * i;
|
|
|
|
//
|
|
if (currentLength > maxAllowedBars)
|
|
{
|
|
currentLength = maxAllowedBars;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Clean ...
|
|
Clean();
|
|
|
|
//
|
|
int llIndex = cBar.FindLowestIndex(
|
|
currentLength,
|
|
MODE_LOW //
|
|
);
|
|
XOHCL llBar;
|
|
result = llBar.Init(
|
|
_Symbol,
|
|
_Period,
|
|
llIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
result = Init(
|
|
_symbol,
|
|
_period,
|
|
llBar.low,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
result = isSupport;
|
|
if (result)
|
|
{
|
|
//
|
|
supportTime = llBar.time;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValid() && isSupport;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Last Resistance for Market and
|
|
// Initialized Pivot Based On it ...
|
|
bool FindLastResistance(
|
|
string _symbol,
|
|
ENUM_TIMEFRAMES _period,
|
|
int barIndex = 0,
|
|
int _supResVerificationsStep = 21 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (_supResVerificationsStep < 0)
|
|
{
|
|
_supResVerificationsStep = 21;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(_symbol) &&
|
|
IsValid(_period) &&
|
|
IsValidSize(_supResVerificationsStep)
|
|
//
|
|
;
|
|
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Resistance ...
|
|
|
|
//
|
|
// Retrieve Current Bar ...
|
|
XOHCL cBar;
|
|
result = cBar.Init(
|
|
_symbol,
|
|
_period,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Available Bars ...
|
|
|
|
//
|
|
int bars = iBars(
|
|
_symbol,
|
|
_period //
|
|
);
|
|
int maxAllowedBars = bars - 500;
|
|
int currentLength = _supResVerificationsStep;
|
|
|
|
//
|
|
// Find Highest High ...
|
|
for (int i = barIndex; i < maxAllowedBars; i++)
|
|
{
|
|
//
|
|
// Validate and Regenrate Current Length ...
|
|
if (i > 1)
|
|
{
|
|
//
|
|
currentLength = _supResVerificationsStep * i;
|
|
|
|
//
|
|
if (currentLength > maxAllowedBars)
|
|
{
|
|
currentLength = maxAllowedBars;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Clean ...
|
|
Clean();
|
|
|
|
//
|
|
int hhIndex = cBar.FindHighestIndex(
|
|
currentLength,
|
|
MODE_HIGH //
|
|
);
|
|
XOHCL hhBar;
|
|
result = hhBar.Init(
|
|
_Symbol,
|
|
_Period,
|
|
hhIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
result = Init(
|
|
_symbol,
|
|
_period,
|
|
hhBar.high,
|
|
barIndex //
|
|
);
|
|
if (!result)
|
|
{
|
|
//
|
|
Clean();
|
|
continue;
|
|
}
|
|
|
|
//
|
|
result = isResistance;
|
|
if (result)
|
|
{
|
|
//
|
|
resistanceTime = hhBar.time;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValid() && isResistance;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Rejection Based On Pivot Type ...
|
|
bool IsRejected()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid() &&
|
|
(
|
|
//
|
|
isSupport ||
|
|
isResistance
|
|
//
|
|
)
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
isSupport
|
|
? IsSupportRejected()
|
|
: IsResistanceRejected()
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Breake Based On Pivot Type ...
|
|
bool IsBreaked()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid() &&
|
|
(
|
|
//
|
|
isSupport ||
|
|
isResistance
|
|
//
|
|
)
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
isSupport
|
|
? IsSupportBreaked()
|
|
: IsResistanceBreaked()
|
|
//
|
|
;
|
|
|
|
//
|
|
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()
|
|
{
|
|
//
|
|
time = NULL;
|
|
symbol = NULL;
|
|
period = NULL;
|
|
supportTime = NULL;
|
|
resistanceTime = NULL;
|
|
|
|
//
|
|
price = 0;
|
|
|
|
//
|
|
breakedAsSupport = 0;
|
|
rejectedAsSupport = 0;
|
|
breakedAsResistance = 0;
|
|
rejectedAsResistance = 0;
|
|
|
|
//
|
|
_lastCalculatedBar = -1;
|
|
|
|
//
|
|
isSupport = false;
|
|
isResistance = false;
|
|
|
|
//
|
|
_objName = NULL;
|
|
}
|
|
|
|
//
|
|
// Validate Model ...
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(symbol) &&
|
|
IsValid(period) &&
|
|
price > 0
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Required Data ...
|
|
void Calculate(
|
|
int barIndex,
|
|
int loopback = 288 //
|
|
)
|
|
{
|
|
//
|
|
if (isSupport || isResistance)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int bars = iBars(
|
|
symbol,
|
|
period //
|
|
);
|
|
|
|
//
|
|
loopback += barIndex;
|
|
|
|
//
|
|
// 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,
|
|
barIndex + 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";
|
|
}
|
|
|
|
//
|
|
// Draw Functions ...
|
|
|
|
//
|
|
// Last Draw Object Name ...
|
|
string _objName;
|
|
|
|
//
|
|
// Draw ...
|
|
bool Draw(
|
|
long _chartId,
|
|
string _prefix = "",
|
|
color _color = clrYellow,
|
|
ENUM_LINE_STYLE _style = STYLE_DOT,
|
|
bool _ray = true,
|
|
int _width = 1,
|
|
int _subWindow = 0,
|
|
bool forcePrefix = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (!isSupport && !isResistance)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
_objName = (IsValid(_prefix) && forcePrefix)
|
|
? _prefix
|
|
: GetTag() + "_" + (IsValid(_prefix) ? _prefix + "_" : "") + ToString(NormalizeDouble(price, 2));
|
|
|
|
//
|
|
int timeBarIndex = iBarShift(
|
|
symbol,
|
|
period,
|
|
time,
|
|
false //
|
|
);
|
|
datetime time1 =
|
|
//
|
|
isSupport
|
|
? supportTime
|
|
: resistanceTime
|
|
//
|
|
;
|
|
|
|
//
|
|
result = DrawTrendLine(
|
|
_chartId,
|
|
_objName,
|
|
_subWindow,
|
|
time1,
|
|
price,
|
|
time,
|
|
price,
|
|
_color,
|
|
_style,
|
|
_width,
|
|
false,
|
|
false,
|
|
_ray //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Remove Draw ...
|
|
void Remove()
|
|
{
|
|
//
|
|
if (!IsValid(_objName))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
RemoveDraws(_objName);
|
|
}
|
|
};
|
|
|
|
//
|
|
// 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 ...
|
|
};
|
|
|
|
//
|
|
// a Zone Consists an Area of
|
|
// an Upper Pivot and a Lower Pivot ...
|
|
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,
|
|
int barIndex = 0,
|
|
int pivotVerificationStep = 21 //
|
|
)
|
|
{
|
|
//
|
|
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,
|
|
barIndex,
|
|
pivotVerificationStep //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = down.Init(
|
|
symbol,
|
|
period,
|
|
_downPrice,
|
|
barIndex,
|
|
pivotVerificationStep //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsValid();
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
time = TimeCurrent();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Last Support Zone ...
|
|
bool FindLastSupportZone(
|
|
string _symbol,
|
|
ENUM_TIMEFRAMES _period,
|
|
int barIndex = 0,
|
|
int pivotVerificationStep = 21 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Since Support Pivots Used Target Bar's Low price
|
|
// Last Resistance Set in Down Line of Zone ...
|
|
result = down.FindLastSupport(
|
|
_symbol,
|
|
_Period,
|
|
barIndex,
|
|
pivotVerificationStep //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Since Support Pivots Used Target Bar's Low price
|
|
// we can Set it's High as Up Zone ...
|
|
XOHCL tBar;
|
|
result = tBar.Init(
|
|
_symbol,
|
|
_period,
|
|
down.supportTime //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Now we Have Target Bar ...
|
|
// Set it's High as Up Line of Zone ...
|
|
result = up.Init(
|
|
_symbol,
|
|
_period,
|
|
tBar.high,
|
|
barIndex,
|
|
pivotVerificationStep //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
up.supportTime = down.supportTime;
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
symbol = _symbol;
|
|
period = _period;
|
|
|
|
//
|
|
time = TimeCurrent();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Last Resistance Zone ...
|
|
bool FindLastResistanceZone(
|
|
string _symbol,
|
|
ENUM_TIMEFRAMES _period,
|
|
int barIndex = 0,
|
|
int pivotVerificationStep = 21 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Since Resistance Pivots Used Target Bar's High price
|
|
// Last Resistance Set in Up Line of Zone ...
|
|
result = up.FindLastResistance(
|
|
_symbol,
|
|
_Period,
|
|
barIndex,
|
|
pivotVerificationStep //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Since Resistance Pivots Used Target Bar's High price
|
|
// we can Set it's Low as Down Zone ...
|
|
XOHCL tBar;
|
|
result = tBar.Init(
|
|
_symbol,
|
|
_period,
|
|
up.resistanceTime //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Now we Have Target Bar ...
|
|
// Set it's Low as Down Line of Zone ...
|
|
result = down.Init(
|
|
_symbol,
|
|
_period,
|
|
tBar.low,
|
|
barIndex,
|
|
pivotVerificationStep //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
down.resistanceTime = up.resistanceTime;
|
|
|
|
//
|
|
if (result)
|
|
{
|
|
//
|
|
symbol = _symbol;
|
|
period = _period;
|
|
|
|
//
|
|
time = TimeCurrent();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
// Check XZone State ...
|
|
ENUM_XZONE_STATE GetState()
|
|
{
|
|
//
|
|
ENUM_XZONE_STATE result = XZONE_STATE_INVALID;
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
// Zone Tools ...
|
|
double _threshold;
|
|
double GetThresholdPoints()
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
if (!IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double _points = GetPoints(symbol);
|
|
result =
|
|
//
|
|
_points &&
|
|
_threshold
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Zone Rejected ...
|
|
bool IsSupportRejected()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Check is Full Support or Not ...
|
|
ENUM_XZONE_STATE state = GetState();
|
|
result = state == XZONE_STATE_FULL_SUPPORT;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// First Check Price Rejection Above Upper Line ...
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Zone Breaked ...
|
|
|
|
//
|
|
// Cleanup ...
|
|
void Clean()
|
|
{
|
|
//
|
|
symbol = NULL;
|
|
period = NULL;
|
|
time = NULL;
|
|
|
|
//
|
|
up.Clean();
|
|
down.Clean();
|
|
|
|
//
|
|
_threshold = 15;
|
|
|
|
//
|
|
_objName = NULL;
|
|
}
|
|
|
|
//
|
|
// Validate ...
|
|
bool IsValid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(symbol) &&
|
|
IsValid(period) &&
|
|
up.IsValid() &&
|
|
down.IsValid() &&
|
|
_threshold > 0
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string GetTag()
|
|
{
|
|
return "XZone";
|
|
}
|
|
|
|
//
|
|
// Draw Functions ...
|
|
|
|
//
|
|
// Last Draw Object Name ...
|
|
string _objName;
|
|
|
|
//
|
|
// Draw ...
|
|
bool Draw(
|
|
long _chartId,
|
|
string _prefix = "",
|
|
color _color = clrYellow,
|
|
ENUM_LINE_STYLE _style = STYLE_DOT,
|
|
bool _ray = true,
|
|
int _width = 1,
|
|
int _subWindow = 0 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ENUM_XZONE_STATE state = GetState();
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid() &&
|
|
state != XZONE_STATE_INVALID
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
_objName = GetTag() + "_" + (IsValid(_prefix) ? _prefix + "_" : "") + ToString(NormalizeDouble(up.price, 2)) + "," + ToString(NormalizeDouble(down.price, 2));
|
|
|
|
//
|
|
datetime time1 =
|
|
//
|
|
down.isSupport
|
|
? down.supportTime
|
|
: down.resistanceTime
|
|
//
|
|
;
|
|
|
|
//
|
|
result = down.Draw(
|
|
_chartId,
|
|
_objName + "_DOWN",
|
|
_color,
|
|
_style,
|
|
_ray,
|
|
_width,
|
|
_subWindow,
|
|
true // Force PRefix ...
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = up.Draw(
|
|
_chartId,
|
|
_objName + "_UP",
|
|
_color,
|
|
_style,
|
|
_ray,
|
|
_width,
|
|
_subWindow,
|
|
true // Force PRefix ...
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Remove Draw ...
|
|
void Remove()
|
|
{
|
|
//
|
|
if (!IsValid(_objName))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
RemoveDraws(_objName);
|
|
}
|
|
};
|
|
|
|
//
|
|
// 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();
|
|
}
|
|
|
|
//
|
|
bool FindTrend(
|
|
string _symbol,
|
|
ENUM_TIMEFRAMES _period,
|
|
int barIndex = 0,
|
|
int _requiredPivots = 5,
|
|
int _requiredShoulders = 5 //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (_requiredPivots < 5)
|
|
{
|
|
_requiredPivots = 5;
|
|
}
|
|
|
|
//
|
|
if (_requiredShoulders < 5)
|
|
{
|
|
_requiredShoulders = 5;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsValid(_symbol) &&
|
|
IsValid(_period)
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Swing Lows and Swing Highs ...
|
|
|
|
//
|
|
int hhIndexes[];
|
|
datetime hhTimes[];
|
|
double hhs[];
|
|
|
|
//
|
|
int llIndexes[];
|
|
datetime llTimes[];
|
|
double lls[];
|
|
|
|
//
|
|
bool isEnough = false;
|
|
int lastHHIndex = barIndex;
|
|
int lastLLIndex = barIndex;
|
|
while (!isEnough)
|
|
{
|
|
//
|
|
int hhSize = ArraySize(hhs);
|
|
if (hhSize < _requiredPivots)
|
|
{
|
|
//
|
|
lastHHIndex = FindSwing(
|
|
_symbol,
|
|
_period,
|
|
X_SWING_HIGH,
|
|
_requiredShoulders,
|
|
lastHHIndex + 1 //
|
|
);
|
|
if (lastHHIndex >= 0)
|
|
{
|
|
//
|
|
XOHCL hBar;
|
|
bool isInited = hBar.Init(
|
|
_symbol,
|
|
_period,
|
|
lastHHIndex //
|
|
);
|
|
if (isInited)
|
|
{
|
|
//
|
|
Add(
|
|
hBar.high,
|
|
hhs //
|
|
);
|
|
|
|
//
|
|
Add(
|
|
hBar.time,
|
|
hhTimes //
|
|
);
|
|
|
|
//
|
|
Add(
|
|
lastHHIndex,
|
|
hhIndexes //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
int llSize = ArraySize(lls);
|
|
if (llSize < _requiredPivots)
|
|
{
|
|
//
|
|
lastLLIndex = FindSwing(
|
|
_symbol,
|
|
_period,
|
|
X_SWING_LOW,
|
|
_requiredShoulders,
|
|
lastLLIndex + 1 //
|
|
);
|
|
if (lastLLIndex >= 0)
|
|
{
|
|
//
|
|
XOHCL lBar;
|
|
bool isInited = lBar.Init(
|
|
_symbol,
|
|
_period,
|
|
lastLLIndex //
|
|
);
|
|
if (isInited)
|
|
{
|
|
//
|
|
Add(
|
|
lBar.low,
|
|
lls //
|
|
);
|
|
|
|
//
|
|
Add(
|
|
lBar.time,
|
|
llTimes //
|
|
);
|
|
|
|
//
|
|
Add(
|
|
lastHHIndex,
|
|
llIndexes //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
hhSize = ArraySize(hhs);
|
|
llSize = ArraySize(lls);
|
|
isEnough =
|
|
//
|
|
hhSize == _requiredPivots &&
|
|
llSize == _requiredPivots
|
|
//
|
|
;
|
|
}
|
|
|
|
// //
|
|
// ArrayReverse(hhs);
|
|
// ArrayReverse(hhTimes);
|
|
// ArrayReverse(hhIndexes);
|
|
|
|
// //
|
|
// ArrayReverse(lls);
|
|
// ArrayReverse(llTimes);
|
|
// ArrayReverse(llIndexes);
|
|
|
|
//
|
|
symbol = _symbol;
|
|
period = _period;
|
|
_numberOfPivots = _requiredPivots;
|
|
_pivotShoulders = _requiredShoulders;
|
|
|
|
//
|
|
result = IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
};
|