last works ...

This commit is contained in:
2025-10-23 16:32:30 +03:30
parent 2edb26cfc2
commit 97bb7b4509
6 changed files with 1237 additions and 583 deletions
@@ -365,9 +365,13 @@ class XCBackTesterEA : public XCBase
ZeroMemory(eaTarget);
//
eaPositionDrawer.Destroy();
delete eaPositionDrawer;
ZeroMemory(eaPositionDrawer);
if (eaPositionDrawer != NULL)
{
//
eaPositionDrawer.Destroy();
delete eaPositionDrawer;
ZeroMemory(eaPositionDrawer);
}
//
delete eaVolume;
@@ -1898,6 +1898,334 @@ class XCMarketPatternDetector : public XCBase
return result;
}
bool HasOrderFlow(
XOHCL &bar,
ENUM_X_DIRECTION &dir,
XBoxZone &orderFlow[],
int orderFlowValidation = 2,
bool containsOBs = false,
bool containsFVGs = true,
bool containsSupportResistances = false,
int zonesLoopback = 5,
int zonesValidationLength = 21,
int maxRequiredZone = 0,
int loopback = 100 //
)
{
//
bool result = false;
//
// Prepare ...
XClean(orderFlow);
CleanDirection(dir);
//
// Normalize ...
loopback = NormalizeInt(loopback, 10);
zonesLoopback = NormalizeInt(zonesLoopback, 3);
maxRequiredZone = NormalizeInt(maxRequiredZone, 0);
orderFlowValidation = NormalizeInt(orderFlowValidation, 1);
zonesValidationLength = NormalizeInt(zonesValidationLength, 3);
//
// Validate ...
result = bar.IsValid();
if (!result)
{
return result;
}
//
// Do ...
//
// Collectiong Zones ...
XBoxZone tmp;
XBoxZone tmps[];
XBoxZone _zones[];
XBoxZone bullishZones[];
XBoxZone bearishZones[];
int bullishZonesCount = 0;
int bearishZonesCount = 0;
//
// Order Blocks ...
if (containsOBs)
{
//
XClean(tmps);
CollectOBs(bar, tmps, zonesLoopback, maxRequiredZone, loopback);
FillNotExists(_zones, tmps);
}
//
// Fair Value Gaps ...
if (containsFVGs)
{
//
XClean(tmps);
CollectFVGs(bar, tmps, zonesLoopback, maxRequiredZone, loopback);
FillNotExists(_zones, tmps);
}
//
// Support and Resistances ...
if (containsSupportResistances)
{
//
XClean(tmps);
CollectZones(bar, tmps, zonesLoopback, maxRequiredZone, loopback);
FillNotExists(_zones, tmps);
}
//
// Validate Zones ...
result = HasChild(_zones);
//
// Extract Only Validated Zones ...
if (result)
{
//
ValidateBoxes(
_zones,
bar.Index() //
);
//
result = HasChild(_zones);
}
//
// Separate Zones Direction ...
if (result)
{
//
bullishZonesCount = ExtractByDirection(bullishZones, _zones, X_DIRECTION_BULLISH);
bearishZonesCount = ExtractByDirection(bearishZones, _zones, X_DIRECTION_BEARISH);
//
result = IsValidSize(bullishZonesCount) ||
IsValidSize(bearishZonesCount);
}
//
// Looking for Sequences of Zones ...
if (result)
{
//
int idx = -1;
bool has = false;
XBoxZone bullOrderFlow[];
XBoxZone bearOrderFlow[];
//
// Bullish OrderFlow ...
//
// Sorting ...
Copy(bullishZones, bullOrderFlow);
Sort(
bullOrderFlow,
X_SORT_BY_DATE,
X_DIRECTION_BEARISH,
orderFlowValidation + 1 //
);
bool hasBullishOrderFlow = ArraySize(bullOrderFlow) >= orderFlowValidation;
if (hasBullishOrderFlow)
{
//
// Validate Order Flow ...
Copy(bullOrderFlow, tmps);
XClean(bullOrderFlow);
while (HasChild(tmps))
{
//
tmp.Clean();
tmp = tmps[0];
ArrayRemove(tmps, 0, 1);
//
idx = GetHighest(tmps);
has = !IsValidIndex(idx)
? true
: tmps[idx].lower < tmp.lower;
if (has)
{
AddIfNotExists(tmp, bullOrderFlow);
}
}
//
hasBullishOrderFlow = ArraySize(bullOrderFlow) >= orderFlowValidation;
}
//
// Bearish OrderFlow ...
//
// Sorting ...
Copy(bearishZones, bearOrderFlow);
Sort(
bearOrderFlow,
X_SORT_BY_DATE,
X_DIRECTION_BULLISH,
orderFlowValidation + 1 //
);
bool hasBearishOrderFlow = ArraySize(bearOrderFlow) >= orderFlowValidation;
if (hasBearishOrderFlow)
{
//
// Validate Order Flow ...
Copy(bearOrderFlow, tmps);
XClean(bearOrderFlow);
while (HasChild(tmps))
{
//
tmp.Clean();
tmp = tmps[0];
ArrayRemove(tmps, 0, 1);
//
idx = GetLowest(tmps);
has = !IsValidIndex(idx)
? true
: tmps[idx].upper > tmp.upper;
if (has)
{
AddIfNotExists(tmp, bearOrderFlow);
}
}
//
hasBearishOrderFlow = ArraySize(bearOrderFlow) >= orderFlowValidation;
}
//
result = hasBullishOrderFlow ||
hasBearishOrderFlow;
//
// Validate Order Flows ...
if (result)
{
//
has = (hasBullishOrderFlow && !hasBearishOrderFlow) ||
(hasBearishOrderFlow && !hasBullishOrderFlow);
//
// When only Have One Direction ...
if (has)
{
//
if (hasBullishOrderFlow)
{
//
dir = X_DIRECTION_BULLISH;
Copy(bullOrderFlow, orderFlow);
}
else if (hasBearishOrderFlow)
{
//
dir = X_DIRECTION_BEARISH;
Copy(bearOrderFlow, orderFlow);
}
}
//
// When Two Direction Exists ...
else
{
//
// Retrieve Oldest Of Bullish / Bearish ...
int oldestBullIDX = GetOldest(bullOrderFlow);
int oldestBearIDX = GetOldest(bearOrderFlow);
result = IsValidIndex(oldestBullIDX) &&
IsValidIndex(oldestBearIDX);
if (result)
{
//
dir =
bullOrderFlow[oldestBullIDX].from > bearOrderFlow[oldestBearIDX].from
? X_DIRECTION_BULLISH
: bearOrderFlow[oldestBearIDX].from > bullOrderFlow[oldestBullIDX].from
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
}
//
result = HasDirection(dir);
if (result)
{
//
if (IsXBullish(dir))
{
Copy(bullOrderFlow, orderFlow);
}
else if (IsXBearish(dir))
{
Copy(bearOrderFlow, orderFlow);
}
}
}
}
//
XClean(bullOrderFlow);
XClean(bearOrderFlow);
//
result = HasChild(orderFlow) &&
HasDirection(dir);
}
//
// Validate Price ...
if (result)
{
//
int idx = -1;
if (IsXBullish(dir))
{
//
idx = GetHighest(orderFlow);
result = IsValidIndex(idx) &&
bar.low > orderFlow[idx].upper;
}
else
{
//
idx = GetLowest(orderFlow);
result = IsValidIndex(idx) &&
bar.high < orderFlow[idx].lower;
}
}
//
// Update To Time of Order Flow ...
if (result)
{
UpdateToTime(orderFlow, bar.time);
}
//
// Cleanup ...
if (!result)
{
//
XClean(orderFlow);
CleanDirection(dir);
}
tmp.Clean();
XClean(tmps);
XClean(_zones);
XClean(bullishZones);
XClean(bearishZones);
//
return result;
}
//
// FVG ...