This commit is contained in:
2025-10-23 13:05:34 +03:30
parent 8b85de5de4
commit 2edb26cfc2
7 changed files with 1267 additions and 85 deletions
+370
View File
@@ -2656,9 +2656,115 @@ class XCXFIMAHelper : public XCBaseHelper
return result;
}
bool IsSarSwitchedToBullish(int barIndex = 0)
{
//
bool result = false;
//
// Normalize ...
barIndex = NormalizeBarIndex(barIndex);
//
int pBarIndex = barIndex + 1;
//
bool isBullish = IsSarBullish(barIndex);
bool isPBullish = IsSarBullish(pBarIndex);
//
result = isBullish &&
!isPBullish;
//
return result;
}
bool IsSarSwitchedToBearish(int barIndex = 0)
{
//
bool result = false;
//
// Normalize ...
barIndex = NormalizeBarIndex(barIndex);
//
int pBarIndex = barIndex + 1;
//
bool isBearish = IsSarBearish(barIndex);
bool isPBearish = IsSarBearish(pBarIndex);
//
result = isBearish &&
!isPBearish;
//
return result;
}
//
// PV ...
bool IsPeakSame(int barIndex = 0)
{
//
bool result = false;
//
// Normalize ...
barIndex = NormalizeBarIndex(barIndex);
//
// Validate ...
result = IsValid();
if (!result)
{
return result;
}
//
double iC = GetPeak(barIndex);
double iP = GetPeak(barIndex + 1);
//
result = iC == iP &&
NotEmptyZero(iC);
//
return result;
}
bool IsValeSame(int barIndex = 0)
{
//
bool result = false;
//
// Normalize ...
barIndex = NormalizeBarIndex(barIndex);
//
// Validate ...
result = IsValid();
if (!result)
{
return result;
}
//
double iC = GetVale(barIndex);
double iP = GetVale(barIndex + 1);
//
result = iC == iP &&
NotEmptyZero(iC);
//
return result;
}
/**
* Check Peak Happens over Last ...
*
@@ -3153,6 +3259,270 @@ class XCXFIMAHelper : public XCBaseHelper
return result;
}
bool HasPVConsolidationZone(
XBoxZone &zone,
int barIndex = 0,
bool forcePVBreak = false,
bool forceHasSarSwitch = false //
)
{
//
bool result = false;
//
// Prepare ...
zone.Clean();
//
// Normalize ...
barIndex = NormalizeBarIndex(barIndex);
//
// Validate ...
result = IsValid();
if (!result)
{
return result;
}
//
// Do ...
//
bool isPeakSame = IsPeakSame(barIndex);
bool isValeSame = IsValeSame(barIndex);
result = !(isPeakSame &&
isValeSame);
if (!result)
{
return result;
}
//
double iPeak = EMPTY_VALUE;
double iVale = EMPTY_VALUE;
//
int idx = barIndex;
bool canLookup = true;
while (canLookup)
{
//
idx++;
isPeakSame = IsPeakSame(idx);
isValeSame = IsValeSame(idx);
result = isPeakSame &&
isValeSame;
if (!result)
{
//
zone.from = GetBarTime(mSymbol, mPeriod, idx);
break;
}
//
if (idx == barIndex + 1)
{
//
zone.to = GetBarTime(
mSymbol,
mPeriod,
idx //
);
}
//
zone.from = GetBarTime(
mSymbol,
mPeriod,
idx //
);
//
iPeak = GetPeak(idx);
iVale = GetVale(idx);
//
zone.lower =
!NotEmptyZero(zone.lower)
? iVale
: MathMin(zone.lower, iVale);
//
zone.upper =
!NotEmptyZero(zone.upper)
? iPeak
: MathMax(zone.upper, iPeak);
}
//
// Validating Zone Params ...
result =
//
IsXValid(zone.to) &&
IsXValid(zone.from) &&
zone.from < zone.to &&
//
NotEmptyZero(zone.lower) &&
NotEmptyZero(zone.upper) &&
zone.upper > zone.lower
//
;
//
// Prepare Zone ...
if (result)
{
//
iPeak = GetPeak(barIndex);
iVale = GetVale(barIndex);
bool isPeakOverLast = IsPeakOverLast(barIndex);
bool isValeUnderLast = IsValeUnderLast(barIndex);
bool isValeBreak = iVale < zone.lower;
bool isPeakBreak = iPeak > zone.upper;
bool isPVBreak = isPeakBreak ||
isValeBreak;
//
zone.at = GetBarTime(mSymbol, mPeriod, barIndex);
zone.symbol = mSymbol;
zone.period = mPeriod;
zone.dir = (isPeakOverLast && !isValeUnderLast && isPVBreak)
? X_DIRECTION_BULLISH
: (isValeUnderLast && !isPeakOverLast && isPVBreak)
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
zone.type = ToXString(X_BAR_PATTERN_CONSOLIDATION);
//
// Refine Zone Upper and Lower ...
if (zone.IsValid())
{
//
XOHCL iBar;
int zoneLoopback = zone.FromIndex() - zone.ToIndex();
result = zone.ToBar(iBar) &&
IsValidSize(zoneLoopback);
if (result)
{
//
double zoneLL = iBar.FindLowest(zoneLoopback, MODE_LOW);
double zoneHH = iBar.FindHighest(zoneLoopback, MODE_HIGH);
result = NotEmptyZero(zoneLL) &&
NotEmptyZero(zoneHH);
if (result)
{
//
zone.lower = zone.lower == zoneLL
? zone.lower
: MathMax(zone.lower, zoneLL);
//
zone.upper = zone.upper == zoneHH
? zone.upper
: MathMin(zone.upper, zoneHH);
}
}
//
iBar.Clean();
}
//
// Validate ...
result = zone.IsValid();
}
//
// Validate Zones From ...
if (result)
{
//
int idx = zone.FromIndex();
//
iPeak = GetPeak(idx);
iVale = GetVale(idx);
//
bool isValeOverLast = IsValeOverLast(idx);
bool isPeakUnderLast = IsPeakUnderLast(idx);
//
result =
result &&
(zone.IsBullish()
? !isPeakUnderLast
: zone.IsBearish()
? !isValeOverLast
: false);
}
//
// Apply Forces ...
//
// PV Break ...
// Peak or Vale must Breaked at Bar ...
if (result && forcePVBreak)
{
//
bool isPVBreaked =
(zone.IsBullish() && IsPeakOverLast(barIndex)) ||
(zone.IsBearish() && IsValeUnderLast(barIndex));
//
result = result &&
isPVBreaked;
}
//
// Other Loop based Forces ...
if (result && (forceHasSarSwitch))
{
//
bool hasSarSwitch = false;
//
int start = zone.ToIndex();
int end = zone.FromIndex();
for (int i = start; i <= end; i++)
{
//
// Check Sar Switches ...
if (forceHasSarSwitch && !hasSarSwitch)
{
//
hasSarSwitch =
zone.IsBullish()
? IsSarSwitchedToBullish(i)
: IsSarSwitchedToBearish(i);
}
}
//
// Validate Forces ...
if (forceHasSarSwitch)
{
//
result =
result &&
hasSarSwitch;
}
}
//
// Cleanup ...
if (!result)
{
zone.Clean();
}
//
return result;
}
//
// HK ...