This commit is contained in:
2025-10-30 18:41:45 +03:30
parent 574c79afcc
commit 7ed6fb61bd
5 changed files with 956 additions and 94 deletions
+692 -94
View File
@@ -2227,6 +2227,450 @@ class XCMarketPatternDetector : public XCBase
return result;
}
//
// Complex ...
/**
* Check Double Pinned Bar ...
*
* @param bar: XOHCL, reference to Specified Bar ...
* @param dir: ENUM_X_DIRECTION, reference to holds Pattern Direction ...
* @param shadowApprovedMultiplier: double, Shadow Size Approve Multiplier ...
* @param minimumPinBarRangeMultiplier: doubble, Range Size Approve Multiplier in Point ...
* @param forceDirection: bool, Apply Force Bar Type ...
* @param loopback: int, Max Allowed Detecting Loopback lenght ...
*
* @return ( bool )
*/
bool IsDoublePinned(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
double shadowApprovedMultiplier = 3,
double minimumPinBarRangeMultiplier = 4,
bool forceDirection = false,
int loopback = 5 //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Normalize ...
loopback = NormalizeInt(loopback, 1);
shadowApprovedMultiplier = NormalizeDouble(shadowApprovedMultiplier, 2, 5);
minimumPinBarRangeMultiplier = NormalizeDouble(minimumPinBarRangeMultiplier, 2, 100);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Do ...
//
// Current Bar Must be a Pinned Bar ...
result = IsPinnedBar(
bar,
dir,
shadowApprovedMultiplier,
minimumPinBarRangeMultiplier,
forceDirection //
);
if (!result)
{
//
CleanDirection(dir);
//
return result;
}
//
XOHCL iBar;
ENUM_X_DIRECTION iDir;
int start = bar.Index() + 1;
int end = start + loopback;
for (int i = start; i < end; i++)
{
//
iBar.Clean();
result = bar.BarAt(i, iBar);
result = result && IsPinnedBar(
iBar,
iDir,
shadowApprovedMultiplier,
minimumPinBarRangeMultiplier,
forceDirection //
);
result = result &&
iDir == dir;
if (result)
{
break;
}
}
//
// Cleanup ...
if (!result)
{
CleanDirection(dir);
}
iBar.Clean();
CleanDirection(iDir);
//
return result;
}
/**
* Check Double Engulfed Bar ...
*
* @param bar: XOHCL, reference to Specified Bar ...
* @param dir: ENUM_X_DIRECTION, reference to holds Pattern Direction ...
* @param loopback: int, Max Allowed Detecting Loopback lenght ...
*
* @return ( bool )
*/
bool IsDoubleEngulfed(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
int loopback = 5 //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Normalize ...
loopback = NormalizeInt(loopback, 1);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Do ...
//
// Current Bar Must be a Pinned Bar ...
result = IsEngulfedBar(
bar,
dir //
);
if (!result)
{
//
CleanDirection(dir);
//
return result;
}
//
XOHCL iBar;
ENUM_X_DIRECTION iDir;
int start = bar.Index() + 1;
int end = start + loopback;
for (int i = start; i < end; i++)
{
//
iBar.Clean();
result = bar.BarAt(i, iBar);
result = result && IsEngulfedBar(
iBar,
iDir //
);
result = result &&
iDir == dir;
if (result)
{
break;
}
}
//
// Cleanup ...
if (!result)
{
CleanDirection(dir);
}
iBar.Clean();
CleanDirection(iDir);
//
return result;
}
/**
* Check Double Momentum Bar ...
*
* @param bar: XOHCL, reference to Specified Bar ...
* @param dir: ENUM_X_DIRECTION, reference to holds Pattern Direction ...
* @param requiredBars: int, bar range for approve Momentum ...
* @param approvedMultiplier: double, a Multipler for approve Momentum ...
* @param loopback: int, Max Allowed Detecting Loopback lenght ...
*
* @return ( bool )
*/
bool IsDoubleMomentum(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
int requiredBars = 3,
double approvedMultiplier = 2,
int loopback = 5 //
)
{
//
bool result = false;
//
// Prepare ...
CleanDirection(dir);
//
// Normalize ...
loopback = NormalizeInt(loopback, 1);
requiredBars = NormalizeInt(requiredBars, 3, 10);
approvedMultiplier = NormalizeDouble(approvedMultiplier, 2, 5);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Do ...
//
// Current Bar Must be a Pinned Bar ...
result = IsMomentumBar(
bar,
dir,
requiredBars,
approvedMultiplier //
);
if (!result)
{
//
CleanDirection(dir);
//
return result;
}
//
XOHCL iBar;
ENUM_X_DIRECTION iDir;
int start = bar.Index() + 1;
int end = start + loopback;
for (int i = start; i < end; i++)
{
//
iBar.Clean();
result = bar.BarAt(i, iBar);
result = result && IsMomentumBar(
iBar,
iDir,
requiredBars,
approvedMultiplier //
);
result = result &&
iDir == dir;
if (result)
{
break;
}
}
//
// Cleanup ...
if (!result)
{
CleanDirection(dir);
}
iBar.Clean();
CleanDirection(iDir);
//
return result;
}
/**
* Check Has Double Patterns ...
*
* @param bar: XOHCL, reference to Specified Bar ...
* @param dir: ENUM_X_DIRECTION, reference to holds Specified Patterns ...
* @param barPatterns: XPatternAnalysis, reference to Provides Bar's Pattern Analysis ...
* @param pBarPatterns: XPatternAnalysis, reference to Provides Previous Bar's Pattern Analysis ...
* @param allowedPatterns: ENUM_X_BAR_PATTERN, collection to Provide Allowed Bar Patterns for Detection ...
* @param config: XPatternAnalysisConfig, Provides Patterns Detection Config ...
* @param loopback: int, Max Allowed Loopback for Detection ...
* @param forDir: ENUM_X_DIRECTION, Specified Patterns Detection Direction ...
*
* @return ( bool )
*/
bool HasDoublePatterns(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
XPatternAnalysis &barPatterns,
XPatternAnalysis &pBarPatterns,
ENUM_X_BAR_PATTERN &allowedPatterns[],
XPatternAnalysisConfig &config,
int loopback = 5,
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
)
{
//
bool result = false;
//
// Prepare ...
barPatterns.Clean();
CleanDirection(dir);
pBarPatterns.Clean();
XPatternAnalysisConfig iConfig = config;
//
// Normalize ...
loopback = NormalizeInt(loopback, 2);
//
// Validate ...
result = bar.IsValid() &&
HasChild(allowedPatterns);
if (!result)
{
return result;
}
//
// Prepare Config ...
iConfig.CleanPatterns();
if (HasChild(allowedPatterns))
{
//
for (int i = 0; i < ArraySize(allowedPatterns); i++)
{
iConfig.AddPattern(allowedPatterns[i]);
}
}
//
// Detect Bar Patterns ...
result = AnalyseBarPatterns(bar, barPatterns, config);
if (!result)
{
//
CleanDirection(dir);
barPatterns.Clean();
pBarPatterns.Clean();
//
return result;
}
//
// Check Direction ...
int bullishCount = barPatterns.Count(X_DIRECTION_BULLISH);
int bearishCount = barPatterns.Count(X_DIRECTION_BEARISH);
dir =
bullishCount > bearishCount
? X_DIRECTION_BULLISH
: bearishCount > bullishCount
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
result = HasDirection(dir);
//
// Check for Dir ...
if (HasDirection(forDir))
{
//
result =
result &&
dir == forDir;
}
//
// Looping Back ...
if (result)
{
//
XOHCL iBar;
ENUM_X_DIRECTION iDir;
int start = bar.Index() + 1;
int end = start + loopback;
for (int i = start; i < end; i++)
{
//
iBar.Clean();
pBarPatterns.Clean();
result = bar.BarAt(i, iBar);
result = result &&
AnalyseBarPatterns(iBar, pBarPatterns, iConfig);
if (!result)
{
continue;
}
//
bullishCount = pBarPatterns.Count(X_DIRECTION_BULLISH);
bearishCount = pBarPatterns.Count(X_DIRECTION_BEARISH);
iDir =
bullishCount > bearishCount
? X_DIRECTION_BULLISH
: bearishCount > bullishCount
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
result = HasDirection(iDir);
result = result &&
dir == iDir;
if (result)
{
break;
}
}
//
iBar.Clean();
CleanDirection(iDir);
}
//
// Cleanup ...
if (!result)
{
//
CleanDirection(dir);
barPatterns.Clean();
pBarPatterns.Clean();
}
iConfig.Clean();
//
return result;
}
//
// Trending ...
@@ -3492,6 +3936,17 @@ class XCMarketPatternDetector : public XCBase
return result;
}
/**
* Collect Required Order Blocks ...
*
* @param bar: XOHCL, reference to Specified Bar ...
* @param dest: XBoxZone, collection reference to holds detected zones ...
* @param zonesLoopback: int, zones detection loopback ...
* @param maxRequiredZone: int, number of required zones ...
* @param loopback: int, max allowed loopback lenght for zone Detection ...
*
* @return ( int )
*/
int CollectOBs(
XOHCL &bar,
XBoxZone &dest[],
@@ -3569,6 +4024,17 @@ class XCMarketPatternDetector : public XCBase
return result;
}
/**
* Collect Required Fair Value Gaps ...
*
* @param bar: XOHCL, reference to Specified Bar ...
* @param dest: XBoxZone, collection reference to holds detected zones ...
* @param zonesLoopback: int, zones detection loopback ...
* @param maxRequiredZone: int, number of required zones ...
* @param loopback: int, max allowed loopback lenght for zone Detection ...
*
* @return ( int )
*/
int CollectFVGs(
XOHCL &bar,
XBoxZone &dest[],
@@ -3646,6 +4112,18 @@ class XCMarketPatternDetector : public XCBase
return result;
}
/**
* Collect Required Support and Resistance Zones ...
*
* @param bar: XOHCL, reference to Specified Bar ...
* @param dest: XBoxZone, collection reference to holds detected zones ...
* @param zonesLoopback: int, zones detection loopback ...
* @param zonesValidationLength: int, zones validation length ...
* @param maxRequiredZone: int, number of required zones ...
* @param loopback: int, max allowed loopback lenght for zone Detection ...
*
* @return ( int )
*/
int CollectZones(
XOHCL &bar,
XBoxZone &dest[],
@@ -3753,6 +4231,220 @@ class XCMarketPatternDetector : public XCBase
return result;
}
/**
* Detect and Collect Required Zones ...
*
* @param bar: XOHCL, reference to Specified Bar ...
* @param zones: XBoxZone, collection reference to holds detected zones ...
* @param validateZones: bool, Specified to Detect only Valid Zones ...
* @param containsOBs: bool, Flag to use Order Block Zones ...
* @param containsFVGs: bool, Flag to use Fair Value Gap Zones ...
* @param containsSupports: bool, Flag to use Support Zones ...
* @param containsResistancess: bool, Flag to use Resistance Zones ...
* @param forDir: ENUM_X_DIRECTION, Specified Zones Direction for Detecting ...
* @param sortby: ENUM_X_SORT_BY, Specified Zones Sorting Factor ...
* @param sortDir: ENUM_X_DIRECTION, Specified Zones Sorting Direction ...
* @param zonesLoopback: int, loop back for Zones Detection ...
* @param zonesValidationLength: int, zones Validation Length ...
* @param count: int, number of required Zones ...
* @param loopback: int, max allowed looping back lenght for detection ...
*
* @return ( int )
*/
int DetectZones(
XOHCL &bar,
XBoxZone &zones[],
bool validateZones = true,
bool removeUsedZones = true,
bool containsOBs = true,
bool containsFVGs = true,
bool containsSupports = true,
bool containsResistancess = true,
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE,
ENUM_X_DIRECTION sortDir = X_DIRECTION_BEARISH,
int zonesLoopback = 5,
int zonesValidationLength = 5,
int count = 0,
int loopback = 500 //
)
{
//
int result = 0;
//
// Prepare ...
XClean(zones);
//
// Normalize ...
count = NormalizeInt(count, 0);
loopback = NormalizeInt(loopback, 50);
zonesLoopback = NormalizeInt(zonesLoopback, 2);
zonesValidationLength = NormalizeInt(zonesValidationLength, 3);
//
// Validate ...
bool has = bar.IsValid() &&
IsXValid(sortDir) &&
IsXValid(sortBy) &&
(containsOBs || containsFVGs || containsSupports || containsResistancess);
if (!has)
{
return result;
}
//
XOHCL iBar;
XOHCL tmpBar;
XPivot tmpPivot;
XBoxZone tmpZone;
ENUM_X_DIRECTION tmpDir;
int idx = bar.Index();
while (idx < bar.Index() + loopback)
{
//
idx++;
//
iBar.Clean();
tmpBar.Clean();
tmpZone.Clean();
tmpPivot.Clean();
//
has = bar.BarAt(idx, iBar);
if (!has)
{
continue;
}
//
// Collecting Zones ...
//
// Support ...
if (containsSupports)
{
//
if (!HasDirection(forDir) || IsXBullish(forDir))
{
//
has = HasSupport(iBar, tmpBar, zonesValidationLength, zonesLoopback);
if (has)
{
//
has = ToBox(tmpBar, tmpZone, X_DIRECTION_BULLISH, X_BAR_PATTERN_SUPPORT);
if (has)
{
AddIfNotExists(tmpZone, zones);
}
}
}
}
//
// Resistance ...
if (containsResistancess)
{
//
if (!HasDirection(forDir) || IsXBearish(forDir))
{
//
has = HasResistance(iBar, tmpBar, zonesValidationLength, zonesLoopback);
if (has)
{
//
has = ToBox(tmpBar, tmpZone, X_DIRECTION_BEARISH, X_BAR_PATTERN_RESISTANCE);
if (has)
{
AddIfNotExists(tmpZone, zones);
}
}
}
}
//
// Order Block ...
if (containsOBs)
{
//
has = HasOB(iBar, tmpDir, tmpZone, zonesLoopback);
if (has && (!HasDirection(forDir) || tmpDir == forDir))
{
AddIfNotExists(tmpZone, zones);
}
}
//
// Fair Value Gaps ...
if (containsFVGs)
{
//
has = HasFVG(iBar, tmpDir, tmpZone, zonesLoopback);
if (has && (!HasDirection(forDir) || tmpDir == forDir))
{
AddIfNotExists(tmpZone, zones);
}
}
}
//
// Validate Zones Exists ...
result = ArraySize(zones);
has = IsValidSize(result);
if (!has)
{
return result;
}
//
// Update Zones Time ...
UpdateToTime(zones, bar.time);
//
// Validate Zones ...
if (validateZones)
{
//
// Apply Zones Validation Here ...
RemoveBreakedZones(zones, true);
}
//
// Remove Filled Zones ...
if (removeUsedZones)
{
//
// Remove all Filled Zones ...
RemoveFilledZones(zones);
}
//
// Apply Sorting ...
Sort(zones, sortBy, sortDir);
//
// Validate Zones Count ...
if (count > 0)
{
CleanupArray(zones, count);
}
//
result = ArraySize(zones);
//
// Cleanup ...
iBar.Clean();
tmpBar.Clean();
tmpZone.Clean();
tmpPivot.Clean();
//
return result;
}
/**
* Filter Zones ...
*
@@ -3842,100 +4534,6 @@ class XCMarketPatternDetector : public XCBase
return result;
}
//
// Trigger Bar ...
bool IsTriggerBar(
XOHCL &bar,
ENUM_X_DIRECTION forDir,
ENUM_TIMEFRAMES forPeriod = PERIOD_M1 //
)
{
//
// Trigger Bars Detected in Specified Perido ...
//
bool result = false;
//
// Validate ...
result = bar.IsValid() &&
IsXValid(forPeriod) &&
HasDirection(forDir);
if (!result)
{
return result;
}
//
// Do ...
//
// Initialized Specified Bar in Specified Time Frame ...
XOHCL periodBar;
int index = GetBarIndex(
bar.symbol,
forPeriod,
TimeCurrent() //
);
result = periodBar.Init(bar.symbol, forPeriod, index);
if (!result)
{
return result;
}
//
// Detect Pattern ...
XPatternAnalysisConfig iConfig;
iConfig.Default();
iConfig.CleanPatterns();
iConfig.AddPattern(X_BAR_PATTERN_LOW);
iConfig.AddPattern(X_BAR_PATTERN_HIGH);
iConfig.AddPattern(X_BAR_PATTERN_PINNED);
iConfig.AddPattern(X_BAR_PATTERN_ENGULFED);
iConfig.AddPattern(X_BAR_PATTERN_SIGNALKEY);
//
XPatternAnalysis periodBarAnalysis;
result = AnalyseBarPatterns(periodBar, periodBarAnalysis, iConfig);
//
bool isBullish =
result &&
IsXBullish(forDir) &&
(
//
periodBarAnalysis.HasPattern(X_BAR_PATTERN_PINNED, X_DIRECTION_BULLISH) ||
periodBarAnalysis.HasPattern(X_BAR_PATTERN_ENGULFED, X_DIRECTION_BULLISH) ||
periodBarAnalysis.HasPattern(X_BAR_PATTERN_SIGNALKEY, X_DIRECTION_BULLISH)
//
);
//
bool isBearish =
result &&
IsXBearish(forDir) &&
(
//
periodBarAnalysis.HasPattern(X_BAR_PATTERN_PINNED, X_DIRECTION_BEARISH) ||
periodBarAnalysis.HasPattern(X_BAR_PATTERN_ENGULFED, X_DIRECTION_BEARISH) ||
periodBarAnalysis.HasPattern(X_BAR_PATTERN_SIGNALKEY, X_DIRECTION_BEARISH)
//
);
//
// Summarize Result ...
result = isBullish || isBearish;
//
// Cleanup ...
iConfig.Clean();
periodBar.Clean();
periodBarAnalysis.Clean();
//
return result;
}
//
// Protected ...
protected: