Files
MQL5Data/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5
T
2026-01-04 16:00:35 +03:30

2396 lines
53 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class
// -------------------------------------------------
// Name: XCX121XKIPoiDetector ...
// Description: X121XKI POI Detector Class ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://saherelm.ir"
#property version "1.00"
#property description "SaherElm X121XKI POI Detector Class"
#property strict
//
// Imports ...
#include "../../Classes/x-saherelm.base.class.mq5"
#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5"
#include "../../Classes/x-saherelm.x-market.pattern.class.mq5"
#include "../../Helpers/x-saherelm.x121.xki.helper.mq5"
#include "../Classes/x-saherelm.x121.xki.parser.class.mq5"
//
// Definitions ...
//
// Implementation ...
class XCX121XKIPOIDetector : public XCMarketPatternDetector
{
//
// Public ...
public:
//
// Props ...
//
string symbol;
ENUM_TIMEFRAMES period;
//
XCBarAnalyser *barAnalyser; // Bar Analyser ...
XCX121XKIHelper *kiHelper; // X121XKI Helper ...
XCX121XKIHelperParser *kiParser; // X121XKI Helper Parser ...
//
// Constructor ...
XCX121XKIPOIDetector(
XCX121XKIHelper *_kiHelper,
XCX121XKIHelperParser *_kiParser //
) : XCMarketPatternDetector()
{
//
barAnalyser = new XCBarAnalyser();
kiHelper = _kiHelper;
kiParser = _kiParser;
//
symbol = kiHelper.GetSymbol();
period = kiHelper.GetPeriod();
}
//
// Deconstructor ...
~XCX121XKIPOIDetector()
{
Destroy();
}
//
// Actions and Tools ...
// #region POI Detectors ...
bool NearestKIFastBullish(
int &index,
int barIndex = 0,
int loopback = 50 //
)
{
//
bool result = false;
//
index = -1;
//
// Normalize ...
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
// Loop Back ...
bool isPassed = false;
for (int i = barIndex; i < barIndex + loopback; i++)
{
//
isPassed = kiParser.IsKIFastBullish(i);
if (isPassed)
{
//
index = i;
break;
}
}
//
result = IsValidIndex(index);
//
return result;
}
bool NearestKIFastBearish(
int &index,
int barIndex = 0,
int loopback = 50 //
)
{
//
bool result = false;
//
index = -1;
//
// Normalize ...
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
// Loop Back ...
bool isPassed = false;
for (int i = barIndex; i < barIndex + loopback; i++)
{
//
isPassed = kiParser.IsKIFastBearish(i);
if (isPassed)
{
//
index = i;
break;
}
}
//
result = IsValidIndex(index);
//
return result;
}
bool NearestKIFastSwitchedToBullish(
int &index,
int barIndex = 0,
int loopback = 50 //
)
{
//
bool result = false;
//
index = -1;
//
// Normalize ...
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
// Loop Back ...
bool isPassed = false;
for (int i = barIndex; i < barIndex + loopback; i++)
{
//
isPassed = kiParser.IsKIFastSwitchedToBullish(i);
if (isPassed)
{
//
index = i;
break;
}
}
//
result = IsValidIndex(index);
//
return result;
}
bool NearestKIFastSwitchedToBearish(
int &index,
int barIndex = 0,
int loopback = 50 //
)
{
//
bool result = false;
//
index = -1;
//
// Normalize ...
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
// Loop Back ...
bool isPassed = false;
for (int i = barIndex; i < barIndex + loopback; i++)
{
//
isPassed = kiParser.IsKIFastSwitchedToBearish(i);
if (isPassed)
{
//
index = i;
break;
}
}
//
result = IsValidIndex(index);
//
return result;
}
bool NearestKISlowBullish(
int &index,
int barIndex = 0,
int loopback = 50 //
)
{
//
bool result = false;
//
index = -1;
//
// Normalize ...
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
// Loop Back ...
bool isPassed = false;
for (int i = barIndex; i < barIndex + loopback; i++)
{
//
isPassed = kiParser.IsKISlowBullish(i);
if (isPassed)
{
//
index = i;
break;
}
}
//
result = IsValidIndex(index);
//
return result;
}
bool NearestKISlowBearish(
int &index,
int barIndex = 0,
int loopback = 50 //
)
{
//
bool result = false;
//
index = -1;
//
// Normalize ...
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
// Loop Back ...
bool isPassed = false;
for (int i = barIndex; i < barIndex + loopback; i++)
{
//
isPassed = kiParser.IsKISlowBearish(i);
if (isPassed)
{
//
index = i;
break;
}
}
//
result = IsValidIndex(index);
//
return result;
}
bool NearestKISlowSwitchedToBullish(
int &index,
int barIndex = 0,
int loopback = 50 //
)
{
//
bool result = false;
//
index = -1;
//
// Normalize ...
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
// Loop Back ...
bool isPassed = false;
for (int i = barIndex; i < barIndex + loopback; i++)
{
//
isPassed = kiParser.IsKISlowSwitchedToBullish(i);
if (isPassed)
{
//
index = i;
break;
}
}
//
result = IsValidIndex(index);
//
return result;
}
bool NearestKISlowSwitchedToBearish(
int &index,
int barIndex = 0,
int loopback = 50 //
)
{
//
bool result = false;
//
index = -1;
//
// Normalize ...
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
// Loop Back ...
bool isPassed = false;
for (int i = barIndex; i < barIndex + loopback; i++)
{
//
isPassed = kiParser.IsKISlowSwitchedToBearish(i);
if (isPassed)
{
//
index = i;
break;
}
}
//
result = IsValidIndex(index);
//
return result;
}
// #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)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
result = kiParser.IsTrendBullish(barIndex) &&
kiParser.IsRSIBullish(barIndex);
if (!result)
{
return result;
}
//
// Add candlestick confirmation ...
XOHCL bar;
result = result &&
bar.Init(symbol, period, barIndex);
if (!result)
{
return result;
}
//
result = result &&
HasCandlestickDirection(
bar,
X_DIRECTION_BULLISH //
);
//
bar.Clean();
//
return result;
}
bool IsBearishPOI(int barIndex = 0)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
result = kiParser.IsTrendBearish(barIndex) &&
kiParser.IsRSIBearish(barIndex);
if (!result)
{
return result;
}
//
// Add candlestick confirmation ...
XOHCL bar;
result = result &&
bar.Init(symbol, period, barIndex);
if (!result)
{
return result;
}
//
result = result &&
HasCandlestickDirection(
bar,
X_DIRECTION_BEARISH //
);
//
bar.Clean();
//
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)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
result = kiParser.IsBullishBreakout(barIndex);
if (!result)
{
return result;
}
//
// Add candlestick confirmation ...
XOHCL bar;
result = result &&
bar.Init(symbol, period, barIndex);
if (!result)
{
return result;
}
//
result = result &&
HasCandlestickDirection(
bar,
X_DIRECTION_BULLISH //
);
//
bar.Clean();
//
return result;
}
bool IsBearishBreakoutPOI(int barIndex = 0)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
result = kiParser.IsBearishBreakout(barIndex);
if (!result)
{
return result;
}
//
// Add candlestick confirmation ...
XOHCL bar;
result = result &&
bar.Init(symbol, period, barIndex);
if (!result)
{
return result;
}
//
result = result &&
HasCandlestickDirection(
bar,
X_DIRECTION_BEARISH //
);
//
bar.Clean();
//
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)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
result = kiParser.IsBullishReversal(barIndex);
if (!result)
{
return result;
}
//
// Add candlestick confirmation ...
XOHCL bar;
result = result &&
bar.Init(symbol, period, barIndex);
if (!result)
{
return result;
}
//
result = result &&
HasCandlestickDirection(
bar,
X_DIRECTION_BULLISH //
);
//
bar.Clean();
//
return result;
}
bool IsBearishReversalPOI(int barIndex = 0)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
result = kiParser.IsBearishReversal(barIndex);
if (!result)
{
return result;
}
//
// Add candlestick confirmation ...
XOHCL bar;
result = result &&
bar.Init(symbol, period, barIndex);
if (!result)
{
return result;
}
//
result = result &&
HasCandlestickDirection(
bar,
X_DIRECTION_BEARISH //
);
//
bar.Clean();
//
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)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
result = kiParser.IsTrendStrongBullish(barIndex);
if (!result)
{
return result;
}
//
// Add candlestick confirmation ...
XOHCL bar;
ENUM_X_DIRECTION dir;
result = result &&
bar.Init(symbol, period, barIndex);
if (!result)
{
return result;
}
//
XOHCL swingBar;
result = result &&
IsFlagPattern(bar, dir, swingBar) &&
IsXBullish(dir);
//
bar.Clean();
swingBar.Clean();
//
return result;
}
bool IsBearishContinuationPOI(int barIndex = 0)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
result = kiParser.IsTrendStrongBearish(barIndex);
if (!result)
{
return result;
}
//
// Add candlestick confirmation ...
XOHCL bar;
ENUM_X_DIRECTION dir;
result = result &&
bar.Init(symbol, period, barIndex);
if (!result)
{
return result;
}
//
XOHCL swingBar;
result = result &&
IsFlagPattern(bar, dir, swingBar) &&
IsXBearish(dir);
//
bar.Clean();
swingBar.Clean();
//
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)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
bool isTrendOk = kiParser.IsTrendStrongBullish(barIndex);
bool isRSIOk = kiParser.IsRSIOverbought(barIndex);
result = isTrendOk && isRSIOk;
if (!result)
{
return result;
}
//
// Add candlestick confirmation ...
XOHCL bar;
result = result &&
bar.Init(symbol, period, barIndex);
if (!result)
{
return result;
}
//
result = result &&
HasCandlestickDirection(
bar,
X_DIRECTION_BEARISH //
);
//
bar.Clean();
//
return result;
}
bool IsBearishExhaustionPOI(int barIndex = 0)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
bool isTrendOk = kiParser.IsTrendStrongBearish(barIndex);
bool isRSIOk = kiParser.IsRSIOversold(barIndex);
result = isTrendOk && isRSIOk;
if (!result)
{
return result;
}
//
// Add candlestick confirmation ...
XOHCL bar;
result = result &&
bar.Init(symbol, period, barIndex);
if (!result)
{
return result;
}
//
result = result &&
HasCandlestickDirection(
bar,
X_DIRECTION_BULLISH //
);
//
bar.Clean();
//
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)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
// Trend was strong in last 3 bars ...
bool isTrendOk = kiParser.IsTrendStrongBullish(barIndex + 1);
for (int i = 1; i <= 3; i++)
{
//
if (kiParser.IsTrendStrongBullish(barIndex + i))
{
isTrendOk = true;
break;
}
}
//
// RSI rolling over from overbought ...
double rsiNow = kiHelper.GetRSI(barIndex);
double rsiPrev = kiHelper.GetRSI(barIndex + 1);
bool rsiFlip = (rsiPrev > 70 && rsiNow < rsiPrev);
bool isRSIOk = rsiFlip || kiParser.IsRSIOverbought(barIndex);
//
bool volCooling = kiHelper.GetATR(barIndex) <= kiHelper.GetATRSmoothed(barIndex) * 1.05;
bool isVolatilityOk = volCooling || kiParser.IsVolatilityLow(barIndex);
//
result = isRSIOk &&
isTrendOk &&
isVolatilityOk;
if (!result)
{
return result;
}
//
// Add candlestick confirmation ...
XOHCL bar;
result = result &&
bar.Init(symbol, period, barIndex);
if (!result)
{
return result;
}
//
result = result &&
HasCandlestickDirection(
bar,
X_DIRECTION_BEARISH //
);
//
bar.Clean();
//
return result;
}
bool IsBearishTrendExhaustedPOI(int barIndex = 0)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
bool isTrendOk = kiParser.IsTrendStrongBearish(barIndex + 1);
for (int i = 1; i <= 3; i++)
{
//
if (kiParser.IsTrendStrongBearish(barIndex + i))
{
isTrendOk = true;
break;
}
}
//
// RSI rolling over from overbought ...
double rsiNow = kiHelper.GetRSI(barIndex);
double rsiPrev = kiHelper.GetRSI(barIndex + 1);
bool rsiFlip = (rsiPrev < 30 && rsiNow > rsiPrev);
bool isRSIOk = rsiFlip || kiParser.IsRSIOversold(barIndex);
//
bool volCooling = kiHelper.GetATR(barIndex) <= kiHelper.GetATRSmoothed(barIndex) * 1.05;
bool isVolatilityOk = volCooling || kiParser.IsVolatilityLow(barIndex);
//
result = isRSIOk &&
isTrendOk &&
isVolatilityOk;
if (!result)
{
return result;
}
//
// Add candlestick confirmation ...
XOHCL bar;
result = result &&
bar.Init(symbol, period, barIndex);
if (!result)
{
return result;
}
//
result = result &&
HasCandlestickDirection(
bar,
X_DIRECTION_BULLISH //
);
//
bar.Clean();
//
return result;
}
// #endregion
// #region XDetectors ...
bool IsKIPOI(
ENUM_X_DIRECTION &dir,
int barIndex = 0 //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
//
bool isBullish = IsKIBullishPOI(barIndex);
bool isBearish = IsKIBearishPOI(barIndex);
//
dir = isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
//
result = HasDirection(dir);
//
return result;
}
bool IsKIBullishPOI(int barIndex = 0)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
result =
kiParser.IsValid() &&
kiParser.IsKISlowBullish(barIndex) &&
kiParser.IsKIFastBearish(barIndex);
//
return result;
}
bool IsKIBearishPOI(int barIndex = 0)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
result =
kiParser.IsValid() &&
kiParser.IsKISlowBearish(barIndex) &&
kiParser.IsKIFastBullish(barIndex);
//
return result;
}
bool IsKISignal(
ENUM_X_DIRECTION &dir, //
int barIndex = 0 //
)
{
//
bool result = false;
//
dir = X_DIRECTION_NONE;
barIndex = kiParser.NormalizeBarIndex(barIndex);
//
// Retrieve KI State ...
bool isBullish = kiParser.IsKIFastSwitchedToBullish(barIndex + 1) &&
kiParser.IsKIFastBullish(barIndex) &&
kiParser.IsKISlowBullish(barIndex);
bool isBearish = kiParser.IsKIFastSwitchedToBearish(barIndex + 1) &&
kiParser.IsKIFastBearish(barIndex) &&
kiParser.IsKISlowBearish(barIndex);
result = isBullish ||
isBearish;
if (!result)
{
return result;
}
//
dir = isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
result = HasDirection(dir);
if (!result)
{
return result;
}
//
XOHCL bar;
result = bar.Init(symbol, period, barIndex + 1);
if (!result)
{
return result;
}
//
// Bar Direction Same as Dir ...
//
// Price Place Check ...
double kiFast = kiHelper.GetKIFast(barIndex + 1);
double kiSlow = kiHelper.GetKISlow(barIndex + 1);
isBullish =
isBullish &&
bar.close > kiFast &&
kiFast > kiSlow &&
(kiParser.IsKIFastOverLast(barIndex + 1) ||
kiParser.IsKISlowOverLast(barIndex + 1));
isBearish =
isBearish &&
bar.close < kiFast &&
kiFast < kiSlow &&
(kiParser.IsKIFastUnderLast(barIndex + 1) ||
kiParser.IsKISlowUnderLast(barIndex + 1));
//
result =
result &&
(isBullish ||
isBearish);
//
// Cleanup Resources ...
bar.Clean();
//
return result;
}
// #endregion
// #region Zone Detectors ...
int DetectSupports(
XBoxZone &zones[],
int barIndex,
int loopback = 50,
bool forceValidation = true,
int validationLength = 7,
int minimumRetests = 2,
double retestThreshold = 10,
int retestLoopback = 100,
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,
minimumRetests,
retestThreshold,
retestLoopback //
);
}
//
result = ArraySize(zones);
//
return result;
}
int DetectResistances(
XBoxZone &zones[],
int barIndex,
int loopback = 50,
bool forceValidation = true,
int validationLength = 7,
int minimumRetests = 2,
double retestThreshold = 10,
int retestLoopback = 100,
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,
minimumRetests,
retestThreshold,
retestLoopback //
);
}
//
result = ArraySize(zones);
//
return result;
}
void ValidateZones(
XBoxZone &zones[],
int barIndex = 0,
int minimumRetests = 2,
double retestThreshold = 10,
int retestLoopback = 100,
ENUM_X_BOUNDARY_PRICE forPriceType = X_BOUNDARY_PRICE_UP_DOWN //
)
{
//
bool has = false;
//
// Validation ...
has = HasChild(zones) &&
IsXValid(forPriceType);
if (!has)
{
return;
}
//
// Normalizetion ...
barIndex = kiParser.NormalizeBarIndex(barIndex);
minimumRetests = NormalizeInt(minimumRetests, 0);
retestLoopback = NormalizeInt(retestLoopback, 50);
retestThreshold = NormalizeDouble(retestThreshold, 5, 10);
//
XOHCL tmpBar;
XBoxZone tmp;
XBoxZone tmps[];
double tmpValue = 0;
for (int i = 0; i < ArraySize(zones); i++)
{
//
tmp = zones[i];
//
if (minimumRetests > 0)
{
//
int retests = CounteZoneTouches(tmp, retestThreshold, retestLoopback);
if (retests < minimumRetests)
{
continue;
}
}
//
// 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 forMinorPeriod = NULL,
ENUM_TIMEFRAMES forMajorPeriod = NULL,
int loopback = 50,
int minorValidation = 7,
int majorValidation = 14,
int minimumRetests = 2,
double retestThreshold = 10,
int retestLoopback = 100 //
)
{
//
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(forMinorPeriod))
{
forMinorPeriod = period;
}
if (!IsXValid(forMajorPeriod))
{
forMajorPeriod = 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,
minimumRetests,
retestThreshold,
retestLoopback,
forSymbol,
forMinorPeriod //
);
if (IsValidSize(supportsCount))
{
//
FillNotExists(
supports,
tmpSupports //
);
//
tmpIDX = GetYoungest(tmpSupports);
if (IsValidIndex(tmpIDX))
{
minorSupport = tmpSupports[tmpIDX];
}
}
//
resistancesCount = DetectResistances(
tmpResistances,
barIndex,
loopback,
true, // Force Validation ...
minorValidation,
minimumRetests,
retestThreshold,
retestLoopback,
forSymbol,
forMinorPeriod //
);
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,
minimumRetests,
retestThreshold,
retestLoopback,
forSymbol,
forMajorPeriod //
);
if (IsValidSize(supportsCount))
{
//
UpdateToTime(tmpSupports);
//
FillNotExists(
supports,
tmpSupports //
);
//
tmpIDX = GetLowest(tmpSupports);
if (IsValidIndex(tmpIDX))
{
majorSupport = tmpSupports[tmpIDX];
}
}
//
resistancesCount = DetectResistances(
tmpResistances,
barIndex,
loopback,
true, // Force Validation ...
majorValidation,
minimumRetests,
retestThreshold,
retestLoopback,
forSymbol,
forMajorPeriod //
);
if (IsValidSize(resistancesCount))
{
//
UpdateToTime(tmpResistances);
//
FillNotExists(
resistances,
tmpResistances //
);
//
tmpIDX = GetHighest(tmpResistances);
if (IsValidIndex(tmpIDX))
{
majorResistance = tmpResistances[tmpIDX];
}
}
//
XClean(tmpSupports);
XClean(tmpResistances);
}
void RefineStructure(
XBoxZone &supports[],
XBoxZone &resistances[],
XBoxZone &minorSupport,
XBoxZone &majorSupport,
XBoxZone &minorResistance,
XBoxZone &majorResistance,
int loopback = 500,
double breakThreshold = 5,
ENUM_X_PRICE breakBy = X_PRICE_CLOSE //
)
{
//
// Support ...
if (HasChild(supports))
{
//
for (int i = 0; i < ArraySize(supports); i++)
{
//
RefineZone(
supports[i],
loopback,
breakThreshold,
breakBy //
);
}
}
//
// Resistance ...
if (HasChild(resistances))
{
//
for (int i = 0; i < ArraySize(resistances); i++)
{
//
RefineZone(
resistances[i],
loopback,
breakThreshold,
breakBy //
);
}
}
//
RefineZone(
minorSupport,
loopback,
breakThreshold,
breakBy //
);
//
RefineZone(
majorSupport,
loopback,
breakThreshold,
breakBy //
);
//
RefineZone(
minorResistance,
loopback,
breakThreshold,
breakBy //
);
//
RefineZone(
majorResistance,
loopback,
breakThreshold,
breakBy //
);
}
int CounteZoneTouches(
XBoxZone &zone,
double threshold = 10,
int loopback = 100 //
)
{
//
int result = 0;
//
// Normalize ...
loopback = NormalizeInt(loopback, 50);
threshold = NormalizeDouble(threshold, 10);
//
if (!zone.IsValid())
{
return result;
}
//
XOHCL tmpBar;
int start = zone.ToIndex();
bool isUpperTouched = false;
bool isLowerTouched = false;
double points = GetPoints(zone.symbol);
double distance = points * threshold;
int end = MathMin(start + loopback, zone.FromIndex());
for (int i = start; i < end; i++)
{
//
if (tmpBar.Init(zone.symbol, zone.period, i))
{
//
isUpperTouched = MathAbs(tmpBar.high - zone.upper) <= distance;
isLowerTouched = MathAbs(tmpBar.low - zone.lower) <= distance;
//
if (
(zone.IsBullish() &&
(isLowerTouched ||
MathAbs(tmpBar.close - zone.lower) <= distance)) ||
(zone.IsBearish() &&
(isUpperTouched ||
MathAbs(tmpBar.close - zone.upper) <= distance)))
{
//
result++;
Add(
tmpBar.time,
zone.tests //
);
}
//
tmpBar.Clean();
}
}
//
tmpBar.Clean();
//
return result;
}
bool HasNearZone(
int &index,
double price,
double threshold,
XBoxZone &zones[] //
)
{
//
bool result = false;
//
index = -1;
//
// Validate ...
result = HasChild(zones) &&
NotEmptyZero(price) &&
NotEmptyZero(threshold) &&
price > 0 &&
threshold > 0;
if (!result)
{
return result;
}
//
double points = GetPoints(zones[0].symbol);
double distance = points * threshold;
for (int i = 0; i < ArraySize(zones); i++)
{
//
// Check Price Distance by Upper ...
result = price >= zones[i].lower - distance &&
price <= zones[i].upper + distance;
if (result)
{
//
index = i;
break;
}
}
//
result = IsValidIndex(index);
//
return result;
}
bool IsNearZone(
double price,
XBoxZone &zone,
double threshold = 0 //
)
{
//
bool result = false;
//
result =
zone.IsValid() &&
NotEmptyZero(price);
if (!result)
{
return result;
}
//
double points = GetPoints(zone.symbol);
double distance = points * threshold;
//
result = price >= zone.lower - distance &&
price <= zone.upper + distance;
//
return result;
}
void RefineZone(
XBoxZone &zone,
int loopback = 500,
double breakThreshold = 5,
ENUM_X_PRICE breakBy = X_PRICE_CLOSE //
)
{
//
bool has =
zone.IsValid() &&
IsXValid(breakBy);
if (!has)
{
return;
}
//
// Normalize ...
loopback = NormalizeInt(loopback, 1);
breakThreshold = NormalizeDouble(breakThreshold, 0, 50);
//
XOHCL iBar;
int start = zone.FromIndex();
int end = start + loopback;
double point = GetPoints(zone.symbol);
double breakDistance = point * breakThreshold;
for (int i = start; i < end; i++)
{
//
has = iBar.Init(zone.symbol, zone.period, i);
if (has)
{
//
// Check Rejections ...
has = zone.IsBullish()
? iBar.low < zone.upper &&
iBar.GetDown() > zone.upper
: iBar.high > zone.upper &&
iBar.GetUp() < zone.upper;
if (has)
{
//
Add(
iBar.time,
zone.tests //
);
}
//
// Check Break ...
double bPrice = iBar.GetPrice(breakBy);
has =
zone.IsBullish()
? bPrice < zone.lower - breakDistance
: bPrice > zone.upper + breakDistance;
if (has)
{
//
zone.breakAt = iBar.time;
break;
}
}
//
iBar.Clean();
}
//
has = IsXValid(zone.breakAt);
if (has)
{
//
zone.at = zone.from;
zone.from = zone.breakAt;
}
}
// #endregion
// #region VolatilitySwitchedHigh ...
bool IsVolatilitySwitchedHigh(
int barIndex = 0,
int loopback = 3 //
)
{
//
bool result = false;
//
barIndex = kiParser.NormalizeBarIndex(barIndex);
loopback = NormalizeInt(loopback, 1);
//
for (int i = barIndex; i < barIndex + loopback; i++)
{
//
result = kiParser.IsVolatilitySwitchdToHigh(i);
if (result)
{
break;
}
}
//
return result;
}
// #endregion
// #region Bar Patterns ...
bool HasRecentPatternTouched(
XBoxZone &zone,
double price,
int barIndex = 0,
int loopback = 5,
int threshold = 5,
ENUM_TIMEFRAMES forPeriod = NULL,
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
)
{
//
bool result = false;
//
zone.Clean();
//
// Validate ...
result = NotEmptyZero(price);
if (!result)
{
return result;
}
//
// Normalize ...
loopback = NormalizeInt(loopback, 2);
barIndex = kiParser.NormalizeBarIndex(barIndex);
if (IsXValid(forPeriod))
{
forPeriod = period;
}
//
XOHCL iBar;
bool has = false;
int iBullishIDX = -1;
int iBearishIDX = -1;
bool isBullish = false;
bool isBearish = false;
XBoxZone iBullishZones[];
XBoxZone iBearishZones[];
XPatternAnalysis iAnalysis;
XPatternAnalysisConfig iConfig;
//
// Preparing Pattern Analysis Config ...
iConfig.Default();
iConfig.FullPattern();
//
for (int i = barIndex; i < barIndex + loopback; i++)
{
//
// Initialize Bar ...
has = iBar.Init(symbol, forPeriod, i);
if (!has)
{
continue;
}
//
// Analyse Patterns ...
has = AnalyseBarPatterns(iBar, iAnalysis, iConfig);
if (!has)
{
//
iBar.Clean();
continue;
}
//
// Bullish ...
has = iAnalysis.Count(X_DIRECTION_BULLISH) > 0;
if (has)
{
//
iAnalysis.GetPatterns(iBullishZones, X_DIRECTION_BULLISH);
has = HasChild(iBullishZones);
if (has)
{
//
has = HasNearZone(
iBullishIDX,
price,
threshold,
iBullishZones //
);
if (has)
{
isBullish = true;
}
}
}
//
// Bearish ...
has = iAnalysis.Count(X_DIRECTION_BEARISH) > 0;
if (has)
{
//
iAnalysis.GetPatterns(iBearishZones, X_DIRECTION_BEARISH);
has = HasChild(iBearishZones);
if (has)
{
//
has = HasNearZone(
iBearishIDX,
price,
threshold,
iBearishZones //
);
if (has)
{
isBearish = true;
}
}
}
//
// Summarizing Result ...
has =
HasDirection(forDir)
? (isBullish && !isBearish && IsXBullish(forDir)) ||
(isBearish && !isBullish && IsXBearish(forDir))
: (isBullish && !isBearish) || (isBearish && !isBullish);
if (has)
{
//
// Fill Zones ...
if (isBullish)
{
zone = iBullishZones[iBullishIDX];
}
else
{
zone = iBearishZones[iBearishIDX];
}
break;
}
//
iBar.Clean();
iAnalysis.Clean();
XClean(iBullishZones);
XClean(iBearishZones);
}
//
// Next
//
iBar.Clean();
iConfig.Clean();
iAnalysis.Clean();
XClean(iBullishZones);
XClean(iBearishZones);
//
return result;
}
// #endregion
//
// Others ...
/**
* Destroy ...
*/
void Destroy()
{
//
delete barAnalyser;
ZeroMemory(barAnalyser);
//
ZeroMemory(kiHelper);
ZeroMemory(kiParser);
}
//
// Testers ...
//
// Protected ...
protected:
//
// Props ...
//
// Private ...
private:
//
//
};
//