Files
xMQL5/BKPS/14041018/Documents/BKP/xfima-zone-detector.bkp.mq5
T
2026-01-08 11:39:42 +03:30

1220 lines
32 KiB
Plaintext

//
// Detectors ...
/**
* Detect Zones (Support / Resistance) based on XFIMA Validators ...
*
* @param zones: XBoxZone, reference to Collection for holding Detected Zones ...
* @param barIndex: int, Specified Start Looking Bar Index ...
* @param onlyValidZones: bool, Only Validation Zones ...
* @param requiredNumberOfZones: int, Specified how many zones looking for ...
* @param shadowMultiplier: double, a valid zone's Shadow side multiplier ...
* @param validationStrength: double, Validation Strength ...
* @param validationLength: int, Validation Length ...
* @param maxAllowedLoopbackLength: int, Specified Max Allowed Looping back trhough Bars for Detection ...
*
* @return ( int )
*/
int DetectXFIMAZones(
XBoxZone &zones[],
int barIndex = 0,
bool onlyValidZones = false,
int requiredNumberOfZones = 50,
double shadowMultiplier = 4,
double validationStrength = 1,
int validationLength = 7,
int maxAllowedLoopbackLength = 1500 //
)
{
//
int result = 0;
//
// Prepare ...
XClean(zones);
//
// Normalize ...
barIndex = NormalizeBarIndex(barIndex);
validationLength = NormalizeInt(validationLength, 3);
shadowMultiplier = NormalizeDouble(shadowMultiplier, 2);
validationStrength = NormalizeDouble(validationStrength, 1);
requiredNumberOfZones = NormalizeInt(requiredNumberOfZones, 5);
maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50);
//
// Validate ...
XOHCL bar;
bool has = IsValid() &&
bar.Init(
mSymbol,
mPeriod,
barIndex + 1 //
);
if (!has)
{
return result;
}
//
// Define Requirements ...
XOHCL iBar;
XBoxZone iBox;
bool isBullish = false;
bool isBearish = false;
double iUpper = EMPTY_VALUE;
double iLower = EMPTY_VALUE;
double iHKUpper = EMPTY_VALUE;
double iHKLower = EMPTY_VALUE;
double iMAUpper = EMPTY_VALUE;
double iMALower = EMPTY_VALUE;
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
//
// Create a Loop to Detect Zones ...
int start = barIndex;
int idx = start - 1;
int end = start + maxAllowedLoopbackLength;
while (ArraySize(zones) < requiredNumberOfZones && idx < end)
{
//
idx++;
//
// Initialize Indexed Bar ...
has = bar.BarAt(idx, iBar);
if (!has)
{
continue;
}
//
// Reading Bars ...
iMAUpper = GetMABondUpper(idx);
iMALower = GetMABondLower(idx);
iHKUpper = GetHKBondUpper(idx);
iHKLower = GetHKBondLower(idx);
//
iUpper = MathMax(iMAUpper, iHKUpper);
iLower = MathMin(iMALower, iHKLower);
//
// Check Bar State ...
has =
NotEmptyZero(iUpper) &&
NotEmptyZero(iLower);
if (!has)
{
continue;
}
//
// Check Direction of Zone ...
isBullish = iBar.low < iLower;
isBearish = iBar.high > iUpper;
has = (isBullish && !isBearish) ||
(isBearish && !isBullish);
if (!has)
{
continue;
}
//
// Validate Price Based on Bar ...
// Validate Shadow Multiplier ...
has =
isBullish
? iBar.low < bar.low
: iBar.high > bar.high;
has =
has &&
(isBullish
? iBar.GetLowShadow() > iBar.GetHighShadow() * shadowMultiplier
: iBar.GetHighShadow() > iBar.GetLowShadow() * shadowMultiplier);
if (!has)
{
continue;
}
//
iDir = isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
// Fill Bax ...
iBox.dir = iDir;
iBox.symbol = mSymbol;
iBox.period = mPeriod;
iBox.upper =
isBullish
? iBar.GetDown()
: iBar.high;
iBox.lower =
isBullish
? iBar.low
: iBar.GetUp();
iBox.type =
(isBullish ? "XFIMA_Support" : "XFIMA_Resistance") + "_" +
ToXString(NormalizePrice(iBox.upper, iBox.symbol)) + "_" +
ToXString(NormalizePrice(iBox.lower, iBox.symbol));
//
iBox.at = iBar.time;
iBox.to = bar.time;
//
// Loopback to Detect From Time ...
XOHCL pBar;
datetime fromTime = NULL;
has = iBar.GetPreviousBar(pBar);
if (has)
{
//
while (!IsXValid(fromTime))
{
//
// Check Price Inside ...
has =
isBullish
? pBar.GetDown() < iBox.lower
: pBar.GetUp() > iBox.upper;
if (has)
{
fromTime = pBar.time;
}
//
// Retrieve PrevBar ...
has = pBar.GetPreviousBar(pBar);
if (!has)
{
break;
}
}
}
has = IsXValid(fromTime);
if (has)
{
iBox.from = fromTime;
}
//
// Validate Zone Length ...
has = iBox.IsValid() &&
(validationStrength >= 1
? iBox.GetRange() >= validationStrength * GetPoints(iBox.symbol)
: true) &&
(iBox.FromIndex() - iBox.AtIndex() >= validationLength);
//
// Validate Zone State ...
if (has)
{
//
// Cleanup Bar ...
iBar.Clean();
//
// Loopingh through At Index ...
for (int i = iBox.ToIndex(); i < iBox.AtIndex(); i++)
{
//
// Initialized Indexed Bar ...
has = bar.BarAt(i, iBar);
if (!has)
{
break;
}
//
// Validate Bar ...
has =
iBox.IsBullish()
? iBar.low > iBox.lower
: iBar.high < iBox.upper;
if (!has)
{
break;
}
}
}
//
if (has)
{
//
AddIfNotExists(
iBox,
zones //
);
}
//
// Cleanup Resources ...
iBar.Clean();
pBar.Clean();
iBox.Clean();
}
//
result = ArraySize(zones);
//
// Cleanup Resources ...
if (!result)
{
XClean(zones);
}
bar.Clean();
iBar.Clean();
iBox.Clean();
//
return result;
}
int DetecteXFIMAPivots(
XPivot &pivots[],
int barIndex = 0,
int requiredNumberOfPivots = 50,
int validationLength = 7,
int maxAllowedLoopbackLength = 1500, //
//
// PV ...
int pvValidationLength = 7,
//
// Momentum ...
int momentumBarValidationLength = 3,
double momentumBarApprovedMultiplier = 3,
//
// TrueGap ...
double trueGapApprovedStrength = 2,
//
// Pin ...
double pinBarShadowApprovedMultiplier = 3,
double pinBarRangeMultiplier = 4,
bool pinBarForceDirection = false,
//
// Flag ...
int flagPatternPullbackLength = 3 //
)
{
//
int result = 0;
//
// Prepare ...
XClean(pivots);
//
// Normalize ...
barIndex = NormalizeBarIndex(barIndex);
validationLength = NormalizeInt(validationLength, 1);
requiredNumberOfPivots = NormalizeInt(requiredNumberOfPivots, 5);
maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50);
//
pvValidationLength = NormalizeInt(pvValidationLength, 0);
//
momentumBarValidationLength = NormalizeInt(momentumBarValidationLength, 2);
momentumBarApprovedMultiplier = NormalizeDouble(momentumBarApprovedMultiplier, 1);
//
trueGapApprovedStrength = NormalizeDouble(trueGapApprovedStrength, 1);
//
pinBarRangeMultiplier = NormalizeDouble(pinBarRangeMultiplier, 4);
pinBarShadowApprovedMultiplier = NormalizeDouble(pinBarShadowApprovedMultiplier, 3);
//
flagPatternPullbackLength = NormalizeInt(flagPatternPullbackLength, 3);
//
// Validate ...
bool has = IsValid();
if (!has)
{
return result;
}
//
XOHCL iBar;
XOHCL tmpBar;
XPivot iPivot;
int count = 0;
string iPrefix = NULL;
int idx = barIndex - 1;
double iMin = EMPTY_VALUE;
double iMax = EMPTY_VALUE;
double iValue = EMPTY_VALUE;
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
ENUM_X_DIRECTION tmpDir = X_DIRECTION_NONE;
ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE;
int end = barIndex + maxAllowedLoopbackLength;
while (
idx < end &&
ArraySize(pivots) < requiredNumberOfPivots)
{
//
idx++;
//
iBar.Clean();
iPivot.Clean();
tmpBar.Clean();
iPrefix = NULL;
iDir = X_DIRECTION_NONE;
//
has = iBar.Init(
mSymbol,
mPeriod,
idx //
);
if (!has)
{
break;
}
//
// Pivots List ...
//
// PV ...
bool isPV = false;
bool isPeak = false;
bool isVale = false;
tmpDir = X_DIRECTION_NONE;
if (pvValidationLength > 0)
{
//
isPV = patternDetector.IsPV(
iBar,
tmpDir,
pvValidationLength //
);
isPeak = isPV &&
IsXBearish(tmpDir);
isVale = isPV &&
IsXBullish(tmpDir);
if (isPV)
{
iPrefix += isPeak ? "XPK" : "XVL";
}
//
// Continue Loopback if PV Validation Provided and not isPV ...
if (!isPV)
{
continue;
}
}
//
// Momentum Bar ...
bool isMomentum = patternDetector.IsMomentumBar(
iBar,
iDir,
momentumBarValidationLength,
momentumBarApprovedMultiplier //
);
if (isMomentum)
{
//
if (!IsXValid(tmpDir))
{
tmpDir = iDir;
}
//
if (iDir != tmpDir)
{
isMomentum = false;
}
else
{
//
count++;
iPrefix += (IsXValid(iPrefix) ? "_" : "") + "MNTM";
}
}
//
// Engulf Bar ...
bool isEngulfed = patternDetector.IsEngulfedBar(
iBar,
iDir //
);
if (isEngulfed)
{
//
if (!IsXValid(tmpDir))
{
tmpDir = iDir;
}
//
if (iDir != tmpDir)
{
isEngulfed = false;
}
else
{
//
count++;
iPrefix += (IsXValid(iPrefix) ? "_" : "") + "ENGLF";
}
}
//
// True Gap ...
bool isTrueGaped = patternDetector.IsTrueGapedBar(
iBar,
iDir,
trueGapApprovedStrength //
);
if (isTrueGaped)
{
//
if (!IsXValid(tmpDir))
{
tmpDir = iDir;
}
//
if (iDir != tmpDir)
{
isTrueGaped = false;
}
else
{
//
count++;
iPrefix += (IsXValid(iPrefix) ? "_" : "") + "TG";
}
}
//
// Pin Bar ...
bool isPinned = patternDetector.IsPinnedBar(
iBar,
iDir,
pinBarShadowApprovedMultiplier,
pinBarRangeMultiplier,
pinBarForceDirection //
);
if (isPinned)
{
//
if (!IsXValid(tmpDir))
{
tmpDir = iDir;
}
//
if (iDir != tmpDir)
{
isPinned = false;
}
else
{
//
count++;
iPrefix += (IsXValid(iPrefix) ? "_" : "") + "PND";
}
}
//
// Patterns ...
//
// Star Pattern ...
bool isStarPattern = patternDetector.IsStarPattern(
iBar,
iDir //
);
if (isStarPattern)
{
//
if (!IsXValid(tmpDir))
{
tmpDir = iDir;
}
//
if (iDir != tmpDir)
{
isStarPattern = false;
}
else
{
//
count++;
iPrefix += (IsXValid(iPrefix) ? "_" : "") + "STR";
}
}
//
// Piercing Pattern ...
bool isPiercingPattern = patternDetector.IsPiercingPattern(
iBar,
iDir //
);
if (isPiercingPattern)
{
//
if (!IsXValid(tmpDir))
{
tmpDir = iDir;
}
//
if (iDir != tmpDir)
{
isPiercingPattern = false;
}
else
{
//
count++;
iPrefix += (IsXValid(iPrefix) ? "_" : "") + "PRCG";
}
}
//
// Rising Pattern ...
bool isRisingPattern = patternDetector.IsRisingPattern(
iBar,
iDir //
);
if (isRisingPattern)
{
//
if (!IsXValid(tmpDir))
{
tmpDir = iDir;
}
//
if (iDir != tmpDir)
{
isRisingPattern = false;
}
else
{
//
count++;
iPrefix += (IsXValid(iPrefix) ? "_" : "") + "RSG";
}
}
//
// Flag Pattern ...
bool isFlagPattern = patternDetector.IsFlagPattern(
iBar,
iDir,
tmpBar,
flagPatternPullbackLength //
);
if (isFlagPattern)
{
//
if (!IsXValid(tmpDir))
{
tmpDir = iDir;
}
//
if (iDir != tmpDir)
{
isFlagPattern = false;
}
else
{
//
count++;
iPrefix += (IsXValid(iPrefix) ? "_" : "") + "FLG";
}
}
//
// Signal Key Pattern ...
bool isSignalKeyPattern = patternDetector.IsSignalKeyBarPattern(
iBar,
iDir,
pinBarShadowApprovedMultiplier,
pinBarRangeMultiplier,
pinBarForceDirection //
);
if (isSignalKeyPattern)
{
//
if (!IsXValid(tmpDir))
{
tmpDir = iDir;
}
//
if (iDir != tmpDir)
{
isSignalKeyPattern = false;
}
else
{
//
count++;
iPrefix += (IsXValid(iPrefix) ? "_" : "") + "SKB";
}
}
//
has =
isPinned ||
isMomentum ||
isEngulfed ||
isTrueGaped ||
isStarPattern ||
isFlagPattern ||
isRisingPattern ||
isPiercingPattern ||
isSignalKeyPattern;
if (!has)
{
continue;
}
// //
// // Validate Pivot Length ...
// // Validate Pivot vs XFIMA Values ...
// for (int i = iBar.Index(); i < iBar.Index() + validationLength; i++)
// {
// //
// tmpBar.Clean();
// has = iBar.BarAt(i, tmpBar);
// if (!has)
// {
// break;
// }
// //
// iMin = EMPTY_VALUE;
// iMax = EMPTY_VALUE;
// has = GetBoundaryValues(
// iMin,
// iMax,
// i //
// );
// //
// // Validate Bar vs TmpBar and Also Boundary Values ...
// has =
// has &&
// (IsXBullish(iDir)
// ?
// // tmpBar.low < iMin &&
// (tmpBar.low > iBar.low ||
// tmpBar.GetDown() || iBar.GetDown())
// :
// // tmpBar.high > iMax &&
// (tmpBar.high < iBar.high ||
// tmpBar.GetUp() < iBar.GetUp()));
// if (!has)
// {
// break;
// }
// //
// iValue = IsXBullish(iDir)
// ? iBar.low
// : iBar.high;
// //
// iType = IsXBullish(iDir)
// ? X_PIVOT_TYPE_VALE
// : X_PIVOT_TYPE_PEAK;
// //
// tmpBar.Clean();
// }
//
has = IsXValid(iPrefix);
if (has)
{
//
iValue = IsXBullish(iDir)
? iBar.low
: iBar.high;
//
iType = IsXBullish(iDir)
? X_PIVOT_TYPE_VALE
: X_PIVOT_TYPE_PEAK;
//
// Preparing Pivot ...
has = iPivot.Init(
iValue,
iBar.time,
iBar.symbol,
iDir,
iBar.period,
iType //
);
if (has)
{
//
iPivot.prefix = iPrefix;
//
AddIfNotExists(
iPivot,
pivots //
);
}
}
//
}
//
// Cleanup Resources ...
iBar.Clean();
iPivot.Clean();
tmpBar.Clean();
//
result = ArraySize(pivots);
//
return result;
}
/**
* Detect XFIMA Based POI Bars ...
*
* @param bars: XOHCL, reference collection to holds detected bars ...
* @param dirs: ENUM_X_DIRECTION, reference collection to holds detected bars Direction ...
* @param barIndex: int, Specified Bar Index ...
* @param forDir: ENUM_X_DIRECTION, specified which Direction of potential bars looking for ...
* @param requiredNumberOfBars: int, Specified how many bars looking for ...
* @param maxAllowedLoopbackLength: int, Specified Max Allowed Looping back trhough Bars for Detection ...
* @return ( int )
*/
int DetectXFIMAPOIBars(
XOHCL &bars[],
ENUM_X_DIRECTION &dirs[],
int barIndex = 0,
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
int requiredNumberOfBars = 300,
int maxAllowedLoopbackLength = 1500 //
)
{
//
int result = 0;
//
// Prepare ...
XClean(bars);
XClean(dirs);
//
// Normalize ...
barIndex = NormalizeBarIndex(barIndex);
requiredNumberOfBars = NormalizeInt(requiredNumberOfBars, 5);
maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50);
//
// Validate ...
bool has = IsValid();
if (!has)
{
return result;
}
//
XOHCL iBar;
int idx = barIndex - 1;
int start = barIndex;
bool isBullish = false;
bool isBearish = false;
double iMin = EMPTY_VALUE;
double iMax = EMPTY_VALUE;
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
int end = start + maxAllowedLoopbackLength;
while (ArraySize(bars) < requiredNumberOfBars ||
idx < maxAllowedLoopbackLength)
{
//
idx++;
has = iBar.Init(
mSymbol,
mPeriod,
idx //
);
if (!has)
{
continue;
}
//
has = GetBoundaryValues(
iMin,
iMax,
idx //
);
if (!has)
{
continue;
}
//
isBullish = iBar.low < iMin;
isBearish = iBar.high > iMax;
has =
!HasDirection(forDir)
? ((isBullish && !isBearish) ||
(isBearish && !isBullish))
: IsXBullish(forDir)
? (isBullish && !isBearish)
: (isBearish && !isBullish);
if (has)
{
//
iDir = isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
AddRef(
iBar,
bars //
);
//
Add(
iDir,
dirs //
);
}
}
//
result = ArraySize(bars);
//
// Cleanup Resources ...
iBar.Clean();
//
return result;
}
int DetectXFIMAReversalPOIBars(
XOHCL &bars[],
ENUM_X_DIRECTION &dirs[],
int barIndex = 0,
bool forceTouchBoundary = false,
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
int requiredNumberOfBars = 300,
int maxAllowedLoopbackLength = 1500 //
)
{
//
int result = 0;
//
// Prepare ...
XClean(bars);
XClean(dirs);
//
// Normalize ...
barIndex = NormalizeBarIndex(barIndex);
requiredNumberOfBars = NormalizeInt(requiredNumberOfBars, 5);
maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50);
//
// Validate ...
bool has = IsValid();
if (!has)
{
return result;
}
//
// Detect POI Bars ...
XOHCL decisionBars[];
ENUM_X_DIRECTION decisionBarDirs[];
int decisionBarsCount = DetectXFIMAPOIBars(
decisionBars,
decisionBarDirs,
barIndex,
forDir,
requiredNumberOfBars,
maxAllowedLoopbackLength //
);
has = IsValidSize(decisionBarsCount);
if (!has)
{
//
XClean(decisionBars);
XClean(decisionBarDirs);
//
return result;
}
//
bool isBullish = false;
bool isBearish = false;
double iMin = EMPTY_VALUE;
double iMax = EMPTY_VALUE;
bool isCond1Bullish = false;
bool isCond1Bearish = false;
for (int i = 0; i < decisionBarsCount; i++)
{
//
// Read Boundary Values ...
has = GetBoundaryValues(iMin, iMax, i);
if (!has)
{
continue;
}
//
// Check Bar Decision Direction ...
isBullish = IsXBullish(decisionBarDirs[i]);
isBearish = IsXBearish(decisionBarDirs[i]);
//
// Validate ...
//
isCond1Bullish = decisionBars[i].IsBullish();
//
isCond1Bearish = decisionBars[i].IsBearish();
//
isBullish =
isBullish &&
(isCond1Bullish);
//
isBearish =
isBearish &&
(isCond1Bearish);
//
if (forceTouchBoundary)
{
//
isBullish =
isBullish &&
(decisionBars[i].high > iMin ||
decisionBars[i].GetUp() > iMin);
//
isBearish =
isBearish &&
(decisionBars[i].low < iMax ||
decisionBars[i].GetDown() < iMax);
}
//
has =
isBullish ||
isBearish;
if (has)
{
//
AddRef(
decisionBars[i],
bars //
);
//
Add(
decisionBarDirs[i],
dirs //
);
}
}
//
result = ArraySize(bars);
//
// Cleanup Resources ...
XClean(decisionBars);
XClean(decisionBarDirs);
//
return result;
}
int DetectXFIMAContinuationalPOIBars(
XOHCL &bars[],
ENUM_X_DIRECTION &dirs[],
int barIndex = 0,
bool forceTouchBoundary = false,
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
int requiredNumberOfBars = 300,
int maxAllowedLoopbackLength = 1500 //
)
{
//
int result = 0;
//
// Prepare ...
XClean(bars);
XClean(dirs);
//
// Normalize ...
barIndex = NormalizeBarIndex(barIndex);
requiredNumberOfBars = NormalizeInt(requiredNumberOfBars, 5);
maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50);
//
// Validate ...
bool has = IsValid();
if (!has)
{
return result;
}
//
// Detect POI Bars ...
XOHCL decisionBars[];
ENUM_X_DIRECTION decisionBarDirs[];
int decisionBarsCount = DetectXFIMAPOIBars(
decisionBars,
decisionBarDirs,
barIndex,
forDir,
requiredNumberOfBars,
maxAllowedLoopbackLength //
);
has = IsValidSize(decisionBarsCount);
if (!has)
{
//
XClean(decisionBars);
XClean(decisionBarDirs);
//
return result;
}
//
bool isBullish = false;
bool isBearish = false;
double iMin = EMPTY_VALUE;
double iMax = EMPTY_VALUE;
bool isCond1Bullish = false;
bool isCond1Bearish = false;
for (int i = 0; i < decisionBarsCount; i++)
{
//
// Read Indexed Bars Boundaries ...
has = GetBoundaryValues(iMin, iMax, decisionBars[i].Index());
if (!has)
{
continue;
}
//
// Make Direction Opposit ...
decisionBarDirs[i] = Opposit(decisionBarDirs[i]);
//
isBullish = IsXBullish(decisionBarDirs[i]);
isBearish = IsXBearish(decisionBarDirs[i]);
//
// Check Bar Validations ...
//
// Cond 1 ...
//
isCond1Bullish =
decisionBars[i].IsBearish() &&
(decisionBars[i].low >= iMax ||
(decisionBars[i].low <= iMax &&
decisionBars[i].GetUp() >= iMax));
//
isCond1Bearish =
decisionBars[i].IsBullish() &&
(decisionBars[i].high <= iMin ||
(decisionBars[i].high >= iMin &&
decisionBars[i].GetDown() <= iMin));
//
isBullish =
isBullish &&
(isCond1Bullish);
//
isBearish =
isBearish &&
(isCond1Bearish);
//
if (forceTouchBoundary)
{
//
isBullish =
isBullish &&
(decisionBars[i].low >= iMax ||
(decisionBars[i].low <= iMax &&
decisionBars[i].GetUp() >= iMax));
//
isBearish =
isBearish &&
(decisionBars[i].high <= iMin ||
(decisionBars[i].high >= iMin &&
decisionBars[i].GetDown() <= iMin));
}
//
has =
isBullish ||
isBearish;
if (has)
{
//
AddRef(
decisionBars[i],
bars //
);
//
Add(
decisionBarDirs[i],
dirs //
);
}
}
//
result = MathMin(ArraySize(bars), ArraySize(dirs));
//
// Cleanup Resources ...
XClean(decisionBars);
XClean(decisionBarDirs);
//
return result;
}