This commit is contained in:
2025-12-31 21:28:54 +03:30
parent ad945b90b2
commit a0876d5a05
12 changed files with 1789 additions and 185 deletions
@@ -384,6 +384,41 @@ class XCX121XKIPOIDetector : public XCMarketPatternDetector
// #endregion
// #region Detectors ...
bool IsPOI(
ENUM_X_DIRECTION &forDir,
int barIndex = 0 //
)
{
//
bool result = false;
//
// Normalize ...
forDir = X_DIRECTION_NONE;
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
bool isBullish = IsBullishPOI(barIndex);
bool isBearish = IsBearishPOI(barIndex);
result = isBullish || isBearish;
if (!result)
{
return result;
}
//
forDir =
isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
result = HasDirection(forDir);
//
return result;
}
bool IsBullishPOI(int barIndex = 0)
{
//
@@ -462,6 +497,41 @@ class XCX121XKIPOIDetector : public XCMarketPatternDetector
return result;
}
bool IsBreakoutPOI(
ENUM_X_DIRECTION &forDir,
int barIndex = 0 //
)
{
//
bool result = false;
//
// Normalize ...
forDir = X_DIRECTION_NONE;
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
bool isBullish = IsBullishBreakoutPOI(barIndex);
bool isBearish = IsBearishBreakoutPOI(barIndex);
result = isBullish || isBearish;
if (!result)
{
return result;
}
//
forDir =
isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
result = HasDirection(forDir);
//
return result;
}
bool IsBullishBreakoutPOI(int barIndex = 0)
{
//
@@ -538,6 +608,41 @@ class XCX121XKIPOIDetector : public XCMarketPatternDetector
return result;
}
bool IsReversalPOI(
ENUM_X_DIRECTION &forDir,
int barIndex = 0 //
)
{
//
bool result = false;
//
// Normalize ...
forDir = X_DIRECTION_NONE;
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
bool isBullish = IsBullishReversalPOI(barIndex);
bool isBearish = IsBearishReversalPOI(barIndex);
result = isBullish || isBearish;
if (!result)
{
return result;
}
//
forDir =
isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
result = HasDirection(forDir);
//
return result;
}
bool IsBullishReversalPOI(int barIndex = 0)
{
//
@@ -614,6 +719,41 @@ class XCX121XKIPOIDetector : public XCMarketPatternDetector
return result;
}
bool IsContinuationPOI(
ENUM_X_DIRECTION &forDir,
int barIndex = 0 //
)
{
//
bool result = false;
//
// Normalize ...
forDir = X_DIRECTION_NONE;
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
bool isBullish = IsBullishContinuationPOI(barIndex);
bool isBearish = IsBearishContinuationPOI(barIndex);
result = isBullish || isBearish;
if (!result)
{
return result;
}
//
forDir =
isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
result = HasDirection(forDir);
//
return result;
}
bool IsBullishContinuationPOI(int barIndex = 0)
{
//
@@ -694,6 +834,41 @@ class XCX121XKIPOIDetector : public XCMarketPatternDetector
return result;
}
bool IsExhaustionPOI(
ENUM_X_DIRECTION &forDir,
int barIndex = 0 //
)
{
//
bool result = false;
//
// Normalize ...
forDir = X_DIRECTION_NONE;
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
bool isBullish = IsBullishExhaustionPOI(barIndex);
bool isBearish = IsBearishExhaustionPOI(barIndex);
result = isBullish || isBearish;
if (!result)
{
return result;
}
//
forDir =
isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
result = HasDirection(forDir);
//
return result;
}
bool IsBullishExhaustionPOI(int barIndex = 0)
{
//
@@ -772,6 +947,41 @@ class XCX121XKIPOIDetector : public XCMarketPatternDetector
return result;
}
bool IsTrendExhaustedPOI(
ENUM_X_DIRECTION &forDir,
int barIndex = 0 //
)
{
//
bool result = false;
//
// Normalize ...
forDir = X_DIRECTION_NONE;
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
bool isBullish = IsBullishTrendExhaustedPOI(barIndex);
bool isBearish = IsBearishTrendExhaustedPOI(barIndex);
result = isBullish || isBearish;
if (!result)
{
return result;
}
//
forDir =
isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
result = HasDirection(forDir);
//
return result;
}
bool IsBullishTrendExhaustedPOI(int barIndex = 0)
{
//
@@ -782,7 +992,7 @@ class XCX121XKIPOIDetector : public XCMarketPatternDetector
//
result = kiParser.IsTrendStrongBullish(barIndex) &&
kiParser.IsVolatilityLow(barIndex, 20) &&
kiParser.IsVolatilityLow(barIndex) &&
kiParser.IsRSIOverbought(barIndex);
if (!result)
{
@@ -822,7 +1032,7 @@ class XCX121XKIPOIDetector : public XCMarketPatternDetector
//
result = kiParser.IsTrendStrongBearish(barIndex) &&
kiParser.IsVolatilityLow(barIndex, 20) &&
kiParser.IsVolatilityLow(barIndex) &&
kiParser.IsRSIOversold(barIndex);
if (!result)
{
@@ -936,6 +1146,533 @@ class XCX121XKIPOIDetector : public XCMarketPatternDetector
}
// #endregion
// #region Zone Detectors ...
int DetectSupports(
XBoxZone &zones[],
int barIndex,
int loopback = 50,
bool forceValidation = true,
int validationLength = 7,
string forSymbol = NULL,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
int result = 0;
//
XClean(zones);
//
// Normalize ...
//
if (barIndex < 0)
{
barIndex = 0;
}
//
if (!IsXValid(forSymbol))
{
forSymbol = symbol;
}
//
if (!IsXValid(forPeriod))
{
forPeriod = period;
}
//
if (loopback < 2)
{
loopback = 2;
}
//
if (validationLength < 2)
{
validationLength = 2;
}
//
// Preparing Loops ...
XOHCL tmpBar;
bool has = false;
double upper = 0;
double lower = 0;
XBoxZone tmpZone;
string type = NULL;
double tmpValue = 0;
datetime from = NULL;
int start = barIndex;
int end = barIndex + loopback;
datetime to = GetBarTime(forSymbol, forPeriod, barIndex);
for (int i = start; i < end; i++)
{
//
// Initialize Bar ...
if (tmpBar.Init(forSymbol, forPeriod, i))
{
//
// Check Has Shadow ...
has = tmpBar.GetHighShadow() > 0 ||
tmpBar.GetLowShadow() > 0;
if (has)
{
//
// Check Support or Resistance ...
//
// Support ...
tmpValue = tmpBar.FindLowest(validationLength, MODE_LOW);
has = NotEmptyZero(tmpValue) &&
tmpValue == tmpBar.low;
if (has)
{
//
tmpZone.Clean();
lower = tmpValue;
from = tmpBar.time;
upper = tmpBar.GetDown();
type = ToXString(X_BAR_PATTERN_SUPPORT);
has = tmpZone.Init(
forSymbol,
forPeriod,
upper,
lower,
from,
to,
X_DIRECTION_BULLISH,
type //
);
if (has)
{
//
AddRef(
tmpZone,
zones //
);
//
tmpZone.Clean();
}
}
}
//
tmpBar.Clean();
}
}
//
// Validate ...
if (HasChild(zones) && forceValidation)
{
ValidateZones(zones, barIndex);
}
//
result = ArraySize(zones);
//
return result;
}
int DetectResistances(
XBoxZone &zones[],
int barIndex,
int loopback = 50,
bool forceValidation = true,
int validationLength = 7,
string forSymbol = NULL,
ENUM_TIMEFRAMES forPeriod = NULL //
)
{
//
int result = 0;
//
XClean(zones);
//
// Normalize ...
//
if (barIndex < 0)
{
barIndex = 0;
}
//
if (!IsXValid(forSymbol))
{
forSymbol = symbol;
}
//
if (!IsXValid(forPeriod))
{
forPeriod = period;
}
//
if (loopback < 2)
{
loopback = 2;
}
//
if (validationLength < 2)
{
validationLength = 2;
}
//
// Preparing Loops ...
XOHCL tmpBar;
bool has = false;
double upper = 0;
double lower = 0;
XBoxZone tmpZone;
string type = NULL;
double tmpValue = 0;
datetime from = NULL;
int start = barIndex;
int end = barIndex + loopback;
datetime to = GetBarTime(forSymbol, forPeriod, barIndex);
for (int i = start; i < end; i++)
{
//
// Initialize Bar ...
if (tmpBar.Init(forSymbol, forPeriod, i))
{
//
// Check Has Shadow ...
has = tmpBar.GetHighShadow() > 0 ||
tmpBar.GetLowShadow() > 0;
if (has)
{
//
// Check Support or Resistance ...
//
// Resistance ...
tmpValue = tmpBar.FindHighest(validationLength, MODE_HIGH);
has = NotEmptyZero(tmpValue) &&
tmpValue == tmpBar.high;
if (has)
{
//
tmpZone.Clean();
upper = tmpValue;
from = tmpBar.time;
lower = tmpBar.GetUp();
type = ToXString(X_BAR_PATTERN_RESISTANCE);
has = tmpZone.Init(
forSymbol,
forPeriod,
upper,
lower,
from,
to,
X_DIRECTION_BEARISH,
type //
);
if (has)
{
//
AddRef(
tmpZone,
zones //
);
//
tmpZone.Clean();
}
}
}
//
tmpBar.Clean();
}
}
//
// Validate ...
if (HasChild(zones) && forceValidation)
{
ValidateZones(zones, barIndex);
}
//
result = ArraySize(zones);
//
return result;
}
void ValidateZones(
XBoxZone &zones[],
int barIndex = 0,
ENUM_X_BOUNDARY_PRICE forPriceType = X_BOUNDARY_PRICE_UP_DOWN //
)
{
//
bool has = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
has = HasChild(zones) &&
IsXValid(forPriceType);
if (!has)
{
return;
}
//
XOHCL tmpBar;
XBoxZone tmp;
XBoxZone tmps[];
double tmpValue = 0;
for (int i = 0; i < ArraySize(zones); i++)
{
//
tmp = zones[i];
//
// Validate Zone ...
has = false;
for (int j = barIndex; j < tmp.FromIndex(); j++)
{
//
// Initial Bar ...
if (tmpBar.Init(tmp.symbol, tmp.period, j))
{
//
tmpValue = forPriceType == X_BOUNDARY_PRICE_UP_DOWN
? tmp.IsBullish()
? tmpBar.GetDown()
: tmpBar.GetUp()
: forPriceType == X_BOUNDARY_PRICE_HIGH_LOW
? tmp.IsBullish()
? tmpBar.low
: tmpBar.high
: EMPTY_VALUE;
if (NotEmptyZero(tmpValue))
{
//
// Check Break ...
has = tmp.IsBullish()
? tmpValue < tmp.lower
: tmpValue > tmp.upper;
//
// If Breakes ...
if (has)
{
break;
}
}
//
tmpBar.Clean();
}
}
//
// Not Breaked ...
if (!has)
{
//
AddIfNotExists(
tmp,
tmps //
);
}
//
tmp.Clean();
}
//
// Update Zones ...
XClean(zones);
Copy(
tmps,
zones //
);
XClean(tmps);
}
void GetCurrentStructure(
XBoxZone &supports[],
XBoxZone &resistances[],
XBoxZone &minorSupport,
XBoxZone &majorSupport,
XBoxZone &minorResistance,
XBoxZone &majorResistance,
int barIndex = 0,
string forSymbol = NULL,
ENUM_TIMEFRAMES forPeriod = NULL,
int loopback = 50,
int minorValidation = 7,
int majorValidation = 14 //
)
{
//
bool has = false;
//
XClean(supports);
XClean(resistances);
minorSupport.Clean();
majorSupport.Clean();
minorResistance.Clean();
majorResistance.Clean();
//
// Normalize ...
barIndex = kiParser.NormalizeBarIndex(barIndex);
if (!IsXValid(forSymbol))
{
forSymbol = symbol;
}
if (!IsXValid(forPeriod))
{
forPeriod = period;
}
//
int tmpIDX = -1;
int supportsCount = 0;
XBoxZone tmpSupports[];
int resistancesCount = 0;
XBoxZone tmpResistances[];
//
// Detect Minors ...
//
supportsCount = DetectSupports(
tmpSupports,
barIndex,
loopback,
true, // Force Validation ...
minorValidation,
forSymbol,
forPeriod //
);
if (IsValidSize(supportsCount))
{
//
FillNotExists(
supports,
tmpSupports //
);
//
tmpIDX = GetYoungest(tmpSupports);
if (IsValidIndex(tmpIDX))
{
minorSupport = tmpSupports[tmpIDX];
}
}
//
resistancesCount = DetectResistances(
tmpResistances,
barIndex,
loopback,
true, // Force Validation ...
minorValidation,
forSymbol,
forPeriod //
);
if (IsValidSize(resistancesCount))
{
//
FillNotExists(
resistances,
tmpResistances //
);
//
tmpIDX = GetYoungest(tmpResistances);
if (IsValidIndex(tmpIDX))
{
minorResistance = tmpResistances[tmpIDX];
}
}
//
XClean(tmpSupports);
XClean(tmpResistances);
//
// Detect Majors ...
//
supportsCount = DetectSupports(
tmpSupports,
barIndex,
loopback,
true, // Force Validation ...
majorValidation,
forSymbol,
forPeriod //
);
if (IsValidSize(supportsCount))
{
//
FillNotExists(
supports,
tmpSupports //
);
//
tmpIDX = GetLowest(tmpSupports);
if (IsValidIndex(tmpIDX))
{
majorSupport = tmpSupports[tmpIDX];
}
}
//
resistancesCount = DetectResistances(
tmpResistances,
barIndex,
loopback,
true, // Force Validation ...
majorValidation,
forSymbol,
forPeriod //
);
if (IsValidSize(resistancesCount))
{
//
FillNotExists(
resistances,
tmpResistances //
);
//
tmpIDX = GetHighest(tmpResistances);
if (IsValidIndex(tmpIDX))
{
majorResistance = tmpResistances[tmpIDX];
}
}
//
XClean(tmpSupports);
XClean(tmpResistances);
}
// #endregion
//
// Others ...