Files
MQL5Data/Classes/x-saherelm.x-helper.class.mq5
T
2026-01-08 20:45:23 +03:30

822 lines
30 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class Library
// ----------------------------------------------
// Name: XSCBaseHelper
// Description: provides all Base Indicator
// Helper requirements ...
//
//
// 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
//
// Includes ...
#include "../Classes/x-saherelm.base.class.mq5"
#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5"
//
// Definitions ...
enum ENUM_X_SCORE
{
X_SCORE_NONE = 0,
X_SCORE_MIN = 1,
X_SCORE_NORMAL = 2,
X_SCORE_MAX = 3,
};
//
// State Handler Generic Functions ...
#define DECLARE_STATE_FUNCTIONS(name, state_reader, bar_normalizer_func) \
bool Is##name##Bullish(int barIndex = 0) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return state_reader(barIndex) >= 1; \
} \
bool Is##name##Bearish(int barIndex = 0) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return state_reader(barIndex) <= -1; \
} \
bool Is##name##SwitchedToBullish(int barIndex = 0) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return Is##name##Bullish(barIndex) && !Is##name##Bullish(barIndex + 1); \
} \
bool Is##name##SwitchedToBearish(int barIndex = 0) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return Is##name##Bearish(barIndex) && !Is##name##Bearish(barIndex + 1); \
}
//
// State Handler Based On Price Type Generic Functions ...
#define DECLARE_PRICE_BASED_STATE_FUNCTIONS(name, value_reader, bar_normalizer_func, point_reader_func, price_reader_func) \
bool Is##name##Bullish(int barIndex = 0, ENUM_X_PRICE priceType = X_PRICE_CLOSE, double tolerance = 2) \
{ \
barIndex = bar_normalizer_func(barIndex); \
double threshold = point_reader_func() * tolerance; \
return price_reader_func(barIndex, priceType) > value_reader(barIndex) + threshold || \
price_reader_func(barIndex, priceType) > value_reader(barIndex) - threshold; \
} \
bool Is##name##Bearish(int barIndex = 0, ENUM_X_PRICE priceType = X_PRICE_CLOSE, double tolerance = 2) \
{ \
barIndex = bar_normalizer_func(barIndex); \
double threshold = point_reader_func() * tolerance; \
return price_reader_func(barIndex, priceType) < value_reader(barIndex) + threshold || \
price_reader_func(barIndex, priceType) < value_reader(barIndex) - threshold; \
} \
bool Is##name##SwitchedToBullish(int barIndex = 0, ENUM_X_PRICE priceType = X_PRICE_CLOSE, double tolerance = 2) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return Is##name##Bullish(barIndex, priceType, tolerance) && !Is##name##Bullish(barIndex + 1, priceType, tolerance); \
} \
bool Is##name##SwitchedToBearish(int barIndex = 0, ENUM_X_PRICE priceType = X_PRICE_CLOSE, double tolerance = 2) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return Is##name##Bearish(barIndex, priceType, tolerance) && !Is##name##Bearish(barIndex + 1, priceType, tolerance); \
}
//
// Value Comparator Generic Functions ...
#define DECLARE_VALUE_COMPARATOR_FUNCTIONS(name, value_reader, bar_normalizer_func, point_reader_func) \
bool Is##name##OverLast(int barIndex = 0, double tolerance = 2) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return IsOver( \
value_reader(barIndex), \
value_reader(barIndex + 1), \
point_reader_func() * tolerance); \
} \
bool Is##name##UnderLast(int barIndex = 0, double tolerance = 2) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return IsUnder( \
value_reader(barIndex), \
value_reader(barIndex + 1), \
point_reader_func() * tolerance); \
} \
bool Is##name##SameAsLast(int barIndex = 0, double tolerance = 2) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return IsSame( \
value_reader(barIndex), \
value_reader(barIndex + 1), \
point_reader_func() * tolerance); \
} \
bool Is##name##CrossedOverLast(int barIndex = 0, double tolerance = 2) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return Is##name##OverLast(barIndex, tolerance) && !Is##name##OverLast(barIndex + 1, tolerance); \
} \
bool Is##name##CrossedUnderLast(int barIndex = 0, double tolerance = 2) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return Is##name##UnderLast(barIndex, tolerance) && !Is##name##UnderLast(barIndex + 1, tolerance); \
}
//
// Price Comparator Generic Functions ...
#define DECLARE_PRICE_COMPARATOR_FUNCTIONS(name, value_reader, bar_normalizer_func, price_reader_func) \
bool IsPriceOver##name(int barIndex = 0, ENUM_X_PRICE priceType = X_PRICE_CLOSE) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return price_reader_func(barIndex, priceType) > value_reader(barIndex); \
} \
bool IsPriceUnder##name(int barIndex = 0, ENUM_X_PRICE priceType = X_PRICE_CLOSE) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return price_reader_func(barIndex, priceType) < value_reader(barIndex); \
} \
bool IsPriceCrossedOver##name(int barIndex = 0, ENUM_X_PRICE priceType = X_PRICE_CLOSE) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return IsPriceOver##name(barIndex, priceType) && !IsPriceOver##name(barIndex + 1, priceType); \
} \
bool IsPriceCrossedUnder##name(int barIndex = 0, ENUM_X_PRICE priceType = X_PRICE_CLOSE) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return IsPriceUnder##name(barIndex, priceType) && !IsPriceUnder##name(barIndex + 1, priceType); \
}
//
// Crossing Comparator Generic Functions ...
#define DECLARE_CROSSING_COMPARATOR_FUNCTIONS(baseName, fastName, slowName, fast_reader_func, slow_reader_func, bar_normalizer_func, point_reader_func) \
bool Is##baseName##fastName##Over##Slow(int barIndex = 0, double tolerance = 2) \
{ \
barIndex = bar_normalizer_func(barIndex); \
double fast = fast_reader_func(barIndex); \
double slow = slow_reader_func(barIndex); \
double distance = tolerance * point_reader_func(); \
return fast > slow && MathAbs(fast - slow) >= distance; \
} \
bool Is##baseName##fastName##Under##Slow(int barIndex = 0, double tolerance = 2) \
{ \
barIndex = bar_normalizer_func(barIndex); \
double fast = fast_reader_func(barIndex); \
double slow = slow_reader_func(barIndex); \
double distance = tolerance * point_reader_func(); \
return fast < slow && MathAbs(fast - slow) >= distance; \
} \
bool Is##baseName##fastName##CrossedOver##Slow(int barIndex = 0, double tolerance = 2) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return Is##baseName##fastName##Over##Slow(barIndex, tolerance) && !Is##baseName##fastName##Over##Slow(barIndex + 1, tolerance); \
} \
bool Is##baseName##fastName##CrossedUnder##Slow(int barIndex = 0, double tolerance = 2) \
{ \
barIndex = bar_normalizer_func(barIndex); \
return Is##baseName##fastName##Under##Slow(barIndex, tolerance) && !Is##baseName##fastName##Under##Slow(barIndex + 1, tolerance); \
}
//
// a Class for Handle base requirements ...
// for indicators ...
class XCBaseHelper : public XCBase
{
//
// Public ...
public:
//
// Constructor ...
XCBaseHelper(
string symbol, // Trading Symbol
ENUM_TIMEFRAMES period // Trading Time Frame
)
{
//
mSymbol = symbol;
mPeriod = period;
}
//
// Deconstructor ...
~XCBaseHelper()
{
//
IndicatorRelease(mHandler);
}
//
// Setter(s) / Getter(s) ...
//
// Symbol ...
string GetSymbol()
{
return mSymbol;
}
//
// Period ...
ENUM_TIMEFRAMES GetPeriod()
{
return mPeriod;
}
//
// Retrieve Bars ...
int CountBars()
{
//
int result =
Bars(
mSymbol,
mPeriod
//
);
//
return result;
}
//
// Retrieve Indicator Calculated Bars ...
int CountCalculatedBars()
{
return BarsCalculated(mHandler);
}
//
virtual void Free()
{
}
//
// Generate Tag ...
virtual string GetTag()
{
//
string result = NULL;
//
result =
//
GetToken() +
"[" +
GetSymbol() + "|" +
ToXString(GetPeriod()) +
"]"
//
;
//
return result;
}
//
// Functions ...
/**
* Validate Handler Exists ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result = IsXValid(mSymbol) &&
IsXValid(mPeriod) &&
mHandler != INVALID_HANDLE;
//
return result;
}
/**
* Extract Validated Zones ...
*
* @param zones: XBoxZone, collection reference to holds results ...
* @param barIndex: int, Specified Bar Index ...
* @param requiredNumberOFZones: int, required Number of Zones ...
* @param breakValidLength: int, Breake Validation Length of Zones ...
* @param validateFakeBreakes: bool, Validation Fake Breaked Zones ...
* @param shadowMultiplier: double a Shadow Multiplier for Validation ...
* @param validationStrength: double, Minimum Strngth Multiplier in Point to Validate ...
* @param validationLength: int, Validation Length of Zones ...
* @param maxAllowedLoopbackLength: int, max Allowed Loopback Length ...
*
* @return ( int )
*/
int ExtractBarZones(
XBoxZone &zones[],
int barIndex = 0,
int requiredNumberOFZones = 50,
int breakValidLength = 3,
bool validateFakeBreakes = true,
double shadowMultiplier = 3,
double validationStrength = 1,
int validationLength = 21,
int maxAllowedLoopbackLength = 1500 //
)
{
//
int result = 0;
//
// Prepare ...
SpecifiedClean(zones);
//
// Normalize ...
barIndex = NormalizeInt(barIndex, 0);
validationLength = NormalizeInt(validationLength, 7);
shadowMultiplier = NormalizeDouble(shadowMultiplier, 1);
validationStrength = NormalizeDouble(validationStrength, 1);
requiredNumberOFZones = NormalizeInt(requiredNumberOFZones, 5);
maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 100);
//
// Reading Values ...
//
string symbol = GetSymbol();
ENUM_TIMEFRAMES period = GetPeriod();
double minAllowedStrength = (validationStrength * GetPoints(symbol));
//
XOHCL bar;
bool has = false;
//
// Initialized Start Bar ...
has = bar.Init(
symbol,
period,
barIndex //
);
if (!has)
{
return result;
}
//
XOHCL iBar;
XBoxZone zone;
int start = barIndex;
bool isBullish = false;
bool isBearish = false;
bool lowShadowPassed = false;
bool highShadowPassed = false;
ENUM_X_DIRECTION dir = X_DIRECTION_NONE;
int end = start + maxAllowedLoopbackLength;
for (int i = start; i < end; i++)
{
//
// Cleanup ...
iBar.Clean();
zone.Clean();
dir = X_DIRECTION_NONE;
//
// Reading HK Buffesr ...
has = bar.BarAt(i, iBar);
if (!has)
{
continue;
}
//
// Check Direction ...
isBullish = iBar.open < iBar.close;
isBearish = iBar.open > iBar.close;
dir =
(isBullish && !isBearish)
? X_DIRECTION_BULLISH
: (isBearish && !isBullish)
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
has = HasDirection(dir);
if (!has)
{
continue;
}
//
// Low Shadow ...
lowShadowPassed = iBar.GetLowShadow() >= (shadowMultiplier * iBar.GetHighShadow());
//
// High Shadow ...
highShadowPassed = iBar.GetHighShadow() >= (shadowMultiplier * iBar.GetLowShadow());
//
has = (lowShadowPassed && !highShadowPassed) ||
(highShadowPassed && !lowShadowPassed);
if (!has)
{
continue;
}
//
// Filling Zone ...
//
zone.symbol = symbol;
zone.period = period;
zone.from = GetBarTime(
zone.symbol,
zone.period,
i //
);
zone.dir = lowShadowPassed
? X_DIRECTION_BULLISH
: highShadowPassed
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
//
zone.upper =
IsXBullish(zone.dir)
? iBar.GetDown()
: IsXBearish(zone.dir)
? iBar.high
: EMPTY_VALUE;
//
zone.lower =
IsXBullish(zone.dir)
? iBar.low
: IsXBearish(zone.dir)
? iBar.GetUp()
: EMPTY_VALUE;
//
zone.to = bar.time;
zone.type = "XBar_" + (IsXBullish(zone.dir) ? "Support" : IsXBearish(zone.dir) ? "Resistance"
: "") +
"_" + ToXString(TimeToSeconds(zone.from));
//
// Validate ...
has =
zone.IsValid() &&
HasDirection(zone.dir) &&
NotEmptyZero(zone.upper) &&
NotEmptyZero(zone.lower) &&
(zone.IsBullish()
? bar.low > zone.upper
: bar.high < zone.lower) &&
(zone.upper - zone.lower) >= minAllowedStrength &&
ValidateBarZone(zone, validationLength, breakValidLength, validateFakeBreakes);
if (has)
{
//
AddIfNotExists(
zone,
zones //
);
}
//
// Cleanup Resources ...
zone.Clean();
//
// Validating ...
result = ArraySize(zones);
has = IsValidSize(result) &&
result >= requiredNumberOFZones;
if (has)
{
break;
}
}
//
// Cleanup Resources ...
bar.Clean();
iBar.Clean();
zone.Clean();
//
return result;
}
/**
* Validate Bar Zone ...
*
* @param zone: XBoxZone, reference to Specified Zone ...
* @param validationLength: int, Validation Length of Zones ...
* @param breakValidLength: int, Break Validation Length of Zones ...
* @param validateFakeBreakes: bool, Validation Fake Breaked Zones ...
*
* @return ( bool )
*/
bool ValidateBarZone(
XBoxZone &zone,
int validationLength = 1,
int breakValidLength = 3,
bool validateFakeBreakes = true //
)
{
//
bool result = false;
//
// Normalize ...
validationLength = NormalizeInt(validationLength, 1);
breakValidLength = NormalizeInt(breakValidLength, 2);
//
// Validate ...
result = zone.IsValid();
if (!result)
{
return result;
}
//
// Requirements ...
XOHCL iBar;
int count = 0;
string symbol = GetSymbol();
ENUM_TIMEFRAMES period = GetPeriod();
//
int start = zone.FromIndex() + 1;
int end = start + validationLength;
//
// Validate Before ...
for (int i = start; i < end; i++)
{
//
// Initialize Indexed Bar ...
iBar.Clean();
result = iBar.Init(
symbol,
period,
i //
);
if (!result)
{
break;
}
//
result = zone.IsBullish()
? iBar.low > zone.lower
: iBar.high < zone.upper;
if (!result)
{
break;
}
}
//
// Validating After ...
if (result)
{
//
start = zone.ToIndex() + 1;
count = zone.FromIndex() - start;
end = start + count;
for (int i = start; i < end; i++)
{
//
// Initialized Indexed Bar ...
iBar.Clean();
result = iBar.Init(
symbol,
period,
i //
);
if (!result)
{
break;
}
//
result = zone.IsBullish()
? iBar.low > zone.lower
: iBar.high < zone.upper;
if (!result)
{
//
// Check For Fake Breake ...
if (validateFakeBreakes && breakValidLength > 0)
{
//
result = i - 1 >= 0;
if (result)
{
//
for (int j = i - 1; j >= zone.ToIndex(); j--)
{
//
// Initialized Indexed Bar ...
iBar.Clean();
result = iBar.Init(
symbol,
period,
j //
);
if (!result)
{
break;
}
//
result = zone.IsBullish()
? iBar.close > zone.upper
: iBar.close < zone.lower;
if (result)
{
//
result = MathAbs(j - i) <= breakValidLength;
if (result)
{
break;
}
}
}
}
}
//
if (!result)
{
break;
}
}
}
}
//
// Cleanup Resource ...
iBar.Clean();
//
return result;
}
/**
* Normalizing Bar Index ...
*
* @param barIndex: int, Provided Bar Index ...
*
* @return ( int )
*/
int NormalizeBarIndex(int barIndex)
{
//
int result = barIndex;
//
if (!IsValid())
{
return result;
}
//
int count = CountBars() - 1;
result = NormalizeInt(result, 0, count - 1);
//
return result;
}
//
// Protected ...
protected:
//
// Props ...
//
// Symbol ...
string mSymbol;
//
// Period ...
ENUM_TIMEFRAMES mPeriod;
//
// Indicator Handler ...
int mHandler;
/**
* Read Value of Specified Buffer ...
*
* @param bufferIndex: int, which handler buffer to read value ...
* @param barIndex: int, Specified Bar Index ...
*
* @return ( double )
*/
double ReadValue(
int bufferIndex,
int barIndex = 0 //
)
{
//
double result = EMPTY_VALUE;
//
// Normalize ...
int barsTotal = CountBars();
barIndex = NormalizeInt(barIndex, 0, barsTotal - 1);
bufferIndex = NormalizeInt(bufferIndex, 0);
//
// Validate ...
if (!IsValid())
{
return result;
}
//
double tmp[];
int count = CopyBuffer(
mHandler,
bufferIndex,
barIndex,
1,
tmp //
);
result = tmp[0];
//
return result;
}
/**
* Read Values of Specified Buffer ...
*
* @param buffer: double, reference collection to holds result ...
* @param bufferIndex: int, which handler buffer to read value ...
* @param barIndex: int, Specified Bar Index ...
* @param count: int, number of items to read, 0 for WHOLE_ARRAY ...
* @param asSeries: bool, set As Series Buffer or not ...
*
* @return ( int )
*/
int ReadValues(
double &buffer[],
int bufferIndex,
int barIndex = 0,
int count = 0,
bool asSeries = true //
)
{
//
int result = 0;
//
// Prepare ...
XClean(buffer);
//
// Normalize ...
int barsTotal = CountBars();
count = NormalizeInt(count, 0);
bufferIndex = NormalizeInt(bufferIndex, 0);
barIndex = NormalizeInt(barIndex, 0, barsTotal - 1);
//
// Validate ...
if (!IsValid())
{
return result;
}
//
result = CopyBuffer(
mHandler,
bufferIndex,
barIndex,
count,
buffer //
);
//
// Set As Series Flag ...
ArraySetAsSeries(buffer, asSeries);
//
result = ArraySize(buffer);
//
return result;
}
//
// Private ...
private:
//
};
//
// Tools ....