5104 lines
102 KiB
Plaintext
5104 lines
102 KiB
Plaintext
|
|
// #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 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 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 Composite ...
|
|
bool IsTrendBullish(int barIndex = 0)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsKIFastBullish(barIndex) &&
|
|
IsKISlowBullish(barIndex) &&
|
|
IsMACrossoverBullish(barIndex);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsTrendBearish(int barIndex = 0)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsKIFastBearish(barIndex) &&
|
|
IsKISlowBearish(barIndex) &&
|
|
IsMACrossoverBearish(barIndex);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsBullishMomentumTrend(int barIndex = 0)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsTrendBullish(barIndex) &&
|
|
IsRSIBullish(barIndex);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsBearishMomentumTrend(int barIndex = 0)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsTrendBearish(barIndex) &&
|
|
IsRSIBearish(barIndex);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsBullishBreakout(int barIndex = 0)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
IsPriceAboveKIUpper(barIndex) &&
|
|
IsATRBreakoutUp(barIndex) &&
|
|
IsVolatilityHigh(barIndex);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsBearishBreakout(int barIndex = 0)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
IsPriceBelowKILower(barIndex) &&
|
|
IsATRBreakoutDown(barIndex) &&
|
|
IsVolatilityHigh(barIndex);
|
|
return result;
|
|
}
|
|
|
|
bool IsBullishReversal(int barIndex = 0)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// RSI oversold and turning upward ...
|
|
double rsiNow = helper.GetRSI(barIndex);
|
|
double rsiPrev = helper.GetRSI(barIndex + 1);
|
|
bool rsiFlip = (rsiNow > rsiPrev) && (rsiPrev < 30);
|
|
|
|
//
|
|
// ATR check (volatility supportive) ...
|
|
double atrNow = helper.GetATR(barIndex);
|
|
double atrPrev = helper.GetATR(barIndex + 1);
|
|
double atrMaNow = helper.GetATRSmoothed(barIndex);
|
|
double atrMaPrev = helper.GetATRSmoothed(barIndex + 1);
|
|
bool atrOk = atrNow > atrMaNow || atrNow > atrPrev || atrMaNow > atrMaPrev;
|
|
|
|
//
|
|
// MA crossover bullish ...
|
|
double maFastNow = helper.GetMAFast(barIndex);
|
|
double maSlowNow = helper.GetMASlow(barIndex);
|
|
bool maOk = maFastNow > maSlowNow;
|
|
|
|
//
|
|
result = rsiFlip && (atrOk || maOk);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsBearishReversal(int barIndex = 0)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// RSI overbought and turning downward ...
|
|
double rsiNow = helper.GetRSI(barIndex);
|
|
double rsiPrev = helper.GetRSI(barIndex + 1);
|
|
bool rsiFlip = (rsiNow < rsiPrev) && (rsiPrev > 70);
|
|
|
|
//
|
|
// ATR check (volatility supportive) ...
|
|
double atrNow = helper.GetATR(barIndex);
|
|
double atrPrev = helper.GetATR(barIndex + 1);
|
|
double atrMaNow = helper.GetATRSmoothed(barIndex);
|
|
double atrMaPrev = helper.GetATRSmoothed(barIndex + 1);
|
|
bool atrOk = atrNow > atrMaNow || atrNow > atrPrev || atrMaNow > atrMaPrev;
|
|
|
|
//
|
|
// MA crossover bearish ...
|
|
double maFastNow = helper.GetMAFast(barIndex);
|
|
double maSlowNow = helper.GetMASlow(barIndex);
|
|
bool maOk = maFastNow < maSlowNow;
|
|
|
|
//
|
|
result = rsiFlip && (atrOk || maOk);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsSafeBullishEntry(int barIndex = 0)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBullishMomentumTrend(barIndex) && !IsRSIOverbought(barIndex);
|
|
return result;
|
|
}
|
|
|
|
bool IsSafeBearishEntry(int barIndex = 0)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBearishMomentumTrend(barIndex) && !IsRSIOversold(barIndex);
|
|
return result;
|
|
}
|
|
|
|
bool IsTrendStrongBullish(int barIndex = 0)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Strong bullish trend requires:
|
|
// - KI Fast bullish
|
|
// - KI Slow bullish
|
|
// - MA crossover bullish
|
|
// - RSI > 60
|
|
// - Volatility high
|
|
result = IsKIFastBullish(barIndex) &&
|
|
IsKISlowBullish(barIndex) &&
|
|
IsMACrossoverBullish(barIndex) &&
|
|
(helper.GetRSI(barIndex) > 60) &&
|
|
IsVolatilityHigh(barIndex);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsTrendStrongBearish(int barIndex = 0)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normalize ...
|
|
barIndex = NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
// Validate ...
|
|
result = IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Strong bearish trend requires:
|
|
// - KI Fast bearish
|
|
// - KI Slow bearish
|
|
// - MA crossover bearish
|
|
// - RSI < 40
|
|
// - Volatility high
|
|
result = IsKIFastBearish(barIndex) &&
|
|
IsKISlowBearish(barIndex) &&
|
|
IsMACrossoverBearish(barIndex) &&
|
|
(helper.GetRSI(barIndex) < 40) &&
|
|
IsVolatilityHigh(barIndex);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Counting Touches ...
|
|
*
|
|
* @param bullish: int reference to holds bullih touches ...
|
|
* @param bearish: int reference to holds bearish touches ...
|
|
* @param barIndex: int, start Bar Index ...
|
|
* @param loopback: int, loopback length for counting ...
|
|
* @param countKIFast: boolean, Count KI Fast ...
|
|
* @param countKISlow: boolean, Count KI Slow ...
|
|
* @param countKIUpper: boolean, Count KI Upper ...
|
|
* @param countKILower: boolean, Count KI Lower ...
|
|
* @param countMAFast: boolean, Count MA Fast ...
|
|
* @param countMASlow: boolean, Count MA Slow ...
|
|
* @param forceClean: boolean, Force Clean results before Start Counting ...
|
|
* @param priceType: ENUM_X_BOUNDARY_PRICE, Specified Price Type for Boundary Countinf ...
|
|
*/
|
|
void CountTouches(
|
|
int &bullish,
|
|
int &bearish,
|
|
int barIndex = 0,
|
|
int loopback = 5,
|
|
bool countKIFast = true,
|
|
bool countKISlow = true,
|
|
bool countKIUpper = true,
|
|
bool countKILower = true,
|
|
bool countMAFast = true,
|
|
bool countMASlow = true,
|
|
bool forceClean = true,
|
|
ENUM_X_BOUNDARY_PRICE priceType = X_BOUNDARY_PRICE_HIGH_LOW //
|
|
)
|
|
{
|
|
//
|
|
if (forceClean)
|
|
{
|
|
bullish = 0;
|
|
bearish = 0;
|
|
}
|
|
|
|
//
|
|
// KI Fast ...
|
|
if (countKIFast)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bullish += CountKIFastTouches(
|
|
barIndex,
|
|
loopback,
|
|
X_DIRECTION_BULLISH,
|
|
priceType //
|
|
);
|
|
|
|
//
|
|
// Bearish ...
|
|
bearish += CountKIFastTouches(
|
|
barIndex,
|
|
loopback,
|
|
X_DIRECTION_BEARISH,
|
|
priceType //
|
|
);
|
|
}
|
|
|
|
//
|
|
// KI Slow ...
|
|
if (countKISlow)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bullish += CountKISlowTouches(
|
|
barIndex,
|
|
loopback,
|
|
X_DIRECTION_BULLISH,
|
|
priceType //
|
|
);
|
|
|
|
//
|
|
// Bearish ...
|
|
bearish += CountKISlowTouches(
|
|
barIndex,
|
|
loopback,
|
|
X_DIRECTION_BEARISH,
|
|
priceType //
|
|
);
|
|
}
|
|
|
|
//
|
|
// KI Upper ...
|
|
if (countKIUpper)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bullish += CountKIUpperTouches(
|
|
barIndex,
|
|
loopback,
|
|
X_DIRECTION_BULLISH,
|
|
priceType //
|
|
);
|
|
|
|
//
|
|
// Bearish ...
|
|
bearish += CountKIUpperTouches(
|
|
barIndex,
|
|
loopback,
|
|
X_DIRECTION_BEARISH,
|
|
priceType //
|
|
);
|
|
}
|
|
|
|
//
|
|
// KI Lower ...
|
|
if (countKILower)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bullish += CountKILowerTouches(
|
|
barIndex,
|
|
loopback,
|
|
X_DIRECTION_BULLISH,
|
|
priceType //
|
|
);
|
|
|
|
//
|
|
// Bearish ...
|
|
bearish += CountKILowerTouches(
|
|
barIndex,
|
|
loopback,
|
|
X_DIRECTION_BEARISH,
|
|
priceType //
|
|
);
|
|
}
|
|
|
|
//
|
|
// KI MA Fast ...
|
|
if (countMAFast)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bullish += CountMAFastTouches(
|
|
barIndex,
|
|
loopback,
|
|
X_DIRECTION_BULLISH,
|
|
priceType //
|
|
);
|
|
|
|
//
|
|
// Bearish ...
|
|
bearish += CountMAFastTouches(
|
|
barIndex,
|
|
loopback,
|
|
X_DIRECTION_BEARISH,
|
|
priceType //
|
|
);
|
|
}
|
|
|
|
//
|
|
// KI MA Slow ...
|
|
if (countMASlow)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bullish += CountMASlowTouches(
|
|
barIndex,
|
|
loopback,
|
|
X_DIRECTION_BULLISH,
|
|
priceType //
|
|
);
|
|
|
|
//
|
|
// Bearish ...
|
|
bearish += CountMASlowTouches(
|
|
barIndex,
|
|
loopback,
|
|
X_DIRECTION_BEARISH,
|
|
priceType //
|
|
);
|
|
}
|
|
}
|
|
// #endregion
|
|
|
|
// #region POI(s) ...
|
|
|
|
// #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;
|
|
|
|
//
|
|
// Validation ...
|
|
has = HasChild(zones) &&
|
|
IsXValid(forPriceType);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Normalizetion ...
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
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 forMinorPeriod = NULL,
|
|
ENUM_TIMEFRAMES forMajorPeriod = 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(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,
|
|
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,
|
|
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,
|
|
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,
|
|
forSymbol,
|
|
forMajorPeriod //
|
|
);
|
|
if (IsValidSize(resistancesCount))
|
|
{
|
|
//
|
|
UpdateToTime(tmpResistances);
|
|
|
|
//
|
|
FillNotExists(
|
|
resistances,
|
|
tmpResistances //
|
|
);
|
|
|
|
//
|
|
tmpIDX = GetHighest(tmpResistances);
|
|
if (IsValidIndex(tmpIDX))
|
|
{
|
|
majorResistance = tmpResistances[tmpIDX];
|
|
}
|
|
}
|
|
|
|
//
|
|
XClean(tmpSupports);
|
|
XClean(tmpResistances);
|
|
}
|
|
|
|
bool HasStructure(
|
|
int barIndex = 0,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forMinorPeriod = NULL,
|
|
ENUM_TIMEFRAMES forMajorPeriod = NULL,
|
|
int loopback = 50,
|
|
int minorValidation = 7,
|
|
int majorValidation = 14 //
|
|
)
|
|
{
|
|
//
|
|
XBoxZone supports[];
|
|
XBoxZone resistances[];
|
|
XBoxZone minorSupport;
|
|
XBoxZone majorSupport;
|
|
XBoxZone minorResistance;
|
|
XBoxZone majorResistance;
|
|
|
|
//
|
|
GetCurrentStructure(
|
|
supports,
|
|
resistances,
|
|
minorSupport,
|
|
majorSupport,
|
|
minorResistance,
|
|
majorResistance,
|
|
barIndex,
|
|
forSymbol,
|
|
forMinorPeriod,
|
|
forMajorPeriod,
|
|
loopback,
|
|
minorValidation,
|
|
majorValidation //
|
|
);
|
|
|
|
//
|
|
bool result =
|
|
majorSupport.IsValid() &&
|
|
majorResistance.IsValid();
|
|
|
|
//
|
|
XClean(supports);
|
|
XClean(resistances);
|
|
minorSupport.Clean();
|
|
majorSupport.Clean();
|
|
minorResistance.Clean();
|
|
majorResistance.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
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 //
|
|
);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
bool DetectRecentSwings(
|
|
XBoxZone &swingHigh,
|
|
XBoxZone &swingLow,
|
|
int barIndex = 0,
|
|
int swingsValidationLength = 50,
|
|
int loopback = 500,
|
|
ENUM_TIMEFRAMES forPeriod = NULL,
|
|
bool forceRefineZones = true //
|
|
)
|
|
{
|
|
//
|
|
swingLow.Clean();
|
|
swingHigh.Clean();
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 5);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
swingsValidationLength = NormalizeInt(swingsValidationLength, 5);
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
XOHCL iBar;
|
|
int iIDX = -1;
|
|
double low = 0;
|
|
double high = 0;
|
|
int lowIDX = -1;
|
|
int highIDX = -1;
|
|
bool has = false;
|
|
double iValue = 0;
|
|
datetime lowAt = NULL;
|
|
datetime highAt = NULL;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
has = iBar.Init(symbol, forPeriod, i);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
iIDX = iBar.FindLowestIndex(swingsValidationLength, MODE_LOW);
|
|
has = IsValidIndex(iIDX);
|
|
if (has)
|
|
{
|
|
//
|
|
iValue = iLow(iBar.symbol, iBar.period, iIDX);
|
|
|
|
//
|
|
// Check Can Set Low ...
|
|
has = (!NotEmptyZero(low) ||
|
|
(NotEmptyZero(low) && iValue < low)) &&
|
|
IsValidSwing(
|
|
iValue,
|
|
iIDX,
|
|
barIndex,
|
|
iBar.symbol,
|
|
iBar.period,
|
|
X_SWING_LOW //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
low = iValue;
|
|
lowIDX = iIDX;
|
|
lowAt = iBar.time;
|
|
}
|
|
}
|
|
|
|
//
|
|
iIDX = iBar.FindHighestIndex(swingsValidationLength, MODE_HIGH);
|
|
has = IsValidIndex(iIDX);
|
|
if (has)
|
|
{
|
|
//
|
|
iValue = iHigh(iBar.symbol, iBar.period, iIDX);
|
|
|
|
//
|
|
// Check Can Set High ...
|
|
has = (!NotEmptyZero(high) ||
|
|
(NotEmptyZero(high) && iValue > high)) &&
|
|
IsValidSwing(
|
|
iValue,
|
|
iIDX,
|
|
barIndex,
|
|
iBar.symbol,
|
|
iBar.period,
|
|
X_SWING_HIGH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
high = iValue;
|
|
highIDX = iIDX;
|
|
highAt = iBar.time;
|
|
}
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
// Recent Low Swing ...
|
|
has =
|
|
IsXValid(lowAt) &&
|
|
NotEmptyZero(low) &&
|
|
IsValidIndex(lowIDX);
|
|
if (has)
|
|
{
|
|
//
|
|
has = iBar.Init(symbol, forPeriod, lowIDX);
|
|
has = has &&
|
|
swingLow.Init(
|
|
iBar.symbol,
|
|
iBar.period,
|
|
iBar.GetDown(),
|
|
low,
|
|
GetBarTime(iBar.symbol, iBar.period, lowIDX + swingsValidationLength - 1),
|
|
GetBarTime(iBar.symbol, iBar.period, barIndex),
|
|
X_DIRECTION_BULLISH,
|
|
ToXString(X_BAR_PATTERN_LOW),
|
|
lowAt //
|
|
);
|
|
if (has && forceRefineZones)
|
|
{
|
|
RefineZone(swingLow, 500, 5, X_PRICE_CLOSE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Recent High Swing ...
|
|
has =
|
|
IsXValid(highAt) &&
|
|
NotEmptyZero(high) &&
|
|
IsValidIndex(highIDX);
|
|
if (has)
|
|
{
|
|
//
|
|
has = iBar.Init(symbol, forPeriod, highIDX);
|
|
has = has &&
|
|
swingHigh.Init(
|
|
iBar.symbol,
|
|
iBar.period,
|
|
high,
|
|
iBar.GetUp(),
|
|
GetBarTime(iBar.symbol, iBar.period, lowIDX + swingsValidationLength - 1),
|
|
GetBarTime(iBar.symbol, iBar.period, barIndex),
|
|
X_DIRECTION_BEARISH,
|
|
ToXString(X_BAR_PATTERN_HIGH),
|
|
highAt //
|
|
);
|
|
if (has && forceRefineZones)
|
|
{
|
|
RefineZone(swingHigh, 500, 5, X_PRICE_CLOSE);
|
|
}
|
|
}
|
|
|
|
//
|
|
bool result = swingLow.IsValid() &&
|
|
swingHigh.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool HasOrderFlow(
|
|
XBoxZone &flow[],
|
|
int barIndex = 0,
|
|
int flowValidationLength = 5,
|
|
ENUM_X_DIRECTION flowDir = X_DIRECTION_NONE,
|
|
int loopback = 50,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL,
|
|
ENUM_X_BOUNDARY_PRICE priceType = X_BOUNDARY_PRICE_HIGH_LOW //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XClean(flow);
|
|
|
|
//
|
|
// Validate ...
|
|
result =
|
|
IsXValid(priceType);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Normalizing Data ...
|
|
if (!IsXValid(forSymbol))
|
|
{
|
|
forSymbol = symbol;
|
|
}
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
loopback = NormalizeInt(loopback, 5);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
flowValidationLength = NormalizeInt(flowValidationLength, 2);
|
|
|
|
//
|
|
// Handle Works ...
|
|
|
|
//
|
|
XOHCL iBar;
|
|
int iIndex = -1;
|
|
bool has = false;
|
|
XBoxZone tmpZone;
|
|
double iPrice = 0;
|
|
ENUM_X_PRICE iPriceType;
|
|
bool isBullish = !HasDirection(flowDir) || IsXBullish(flowDir);
|
|
bool isBearish = !HasDirection(flowDir) || IsXBearish(flowDir);
|
|
|
|
//
|
|
// Looping Reversal ...
|
|
int start = barIndex + loopback;
|
|
int end = barIndex;
|
|
for (int i = start; i > end; i--)
|
|
{
|
|
//
|
|
has = iBar.Init(forSymbol, forPeriod, i);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check iBar is Low Swing ...
|
|
if (isBullish)
|
|
{
|
|
//
|
|
iPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW
|
|
? X_PRICE_LOW
|
|
: X_PRICE_DOWN;
|
|
iPrice = iBar.GetPrice(iPriceType);
|
|
has = iPrice == iBar.FindLowest(iIndex, flowValidationLength, iPriceType);
|
|
has = has &&
|
|
IsValidSwing(
|
|
iPrice,
|
|
iBar.Index(),
|
|
barIndex,
|
|
iBar.symbol,
|
|
iBar.period,
|
|
X_SWING_LOW //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Flow Detected ...
|
|
tmpZone.Clean();
|
|
iPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW
|
|
? X_PRICE_DOWN
|
|
: X_PRICE_UP;
|
|
has = tmpZone.Init(
|
|
iBar.symbol,
|
|
iBar.period,
|
|
iBar.GetPrice(iPriceType),
|
|
iPrice,
|
|
iBar.time,
|
|
GetBarTime(iBar.symbol, iBar.period, barIndex),
|
|
X_DIRECTION_BULLISH,
|
|
ToXString(X_BAR_PATTERN_LOW) //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
tmpZone,
|
|
flow //
|
|
);
|
|
|
|
//
|
|
tmpZone.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check iBar is High Swing ...
|
|
if (isBearish)
|
|
{
|
|
//
|
|
iPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW
|
|
? X_PRICE_HIGH
|
|
: X_PRICE_UP;
|
|
iPrice = iBar.GetPrice(iPriceType);
|
|
has = iPrice == iBar.FindHighest(iIndex, flowValidationLength, iPriceType);
|
|
has = has &&
|
|
IsValidSwing(
|
|
iPrice,
|
|
iBar.Index(),
|
|
barIndex,
|
|
iBar.symbol,
|
|
iBar.period,
|
|
X_SWING_HIGH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
// Flow Detected ...
|
|
tmpZone.Clean();
|
|
iPriceType = priceType == X_BOUNDARY_PRICE_HIGH_LOW
|
|
? X_PRICE_UP
|
|
: X_PRICE_DOWN;
|
|
has = tmpZone.Init(
|
|
iBar.symbol,
|
|
iBar.period,
|
|
iPrice,
|
|
iBar.GetPrice(iPriceType),
|
|
iBar.time,
|
|
GetBarTime(iBar.symbol, iBar.period, barIndex),
|
|
X_DIRECTION_BEARISH,
|
|
ToXString(X_BAR_PATTERN_HIGH) //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
tmpZone,
|
|
flow //
|
|
);
|
|
|
|
//
|
|
tmpZone.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
tmpZone.Clean();
|
|
}
|
|
|
|
//
|
|
result = HasChild(flow);
|
|
if (result)
|
|
{
|
|
Sort(flow);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsValidSwing(
|
|
double price,
|
|
int swingIDX,
|
|
int barIndex = 0,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL,
|
|
ENUM_X_SWING_TYPE swingType = X_SWING_NONE //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
NotEmptyZero(price) &&
|
|
IsXValid(swingType) &&
|
|
IsValidIndex(swingIDX) &&
|
|
swingIDX >= barIndex;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsXValid(forSymbol))
|
|
{
|
|
forSymbol = symbol;
|
|
}
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool has = false;
|
|
for (int i = barIndex; i <= (swingIDX - barIndex); i++)
|
|
{
|
|
//
|
|
has = iBar.Init(forSymbol, forPeriod, i);
|
|
if (!has)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check Price Break ...
|
|
has =
|
|
(swingType == X_SWING_LOW &&
|
|
iBar.low < price) ||
|
|
(swingType == X_SWING_HIGH &&
|
|
iBar.high > price);
|
|
if (has)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
result = !has && !iBar.IsValid();
|
|
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
// #endregion
|
|
|
|
// #region Hasers ...
|
|
bool HasVolatilitySwitchedHigh(
|
|
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 ...
|
|
void FillStrategy1Patterns(
|
|
ENUM_X_BAR_PATTERN &patterns[],
|
|
ENUM_X_DIRECTION &dirs[],
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
XClean(dirs);
|
|
XClean(patterns);
|
|
|
|
//
|
|
if (!IsXValid(forSymbol))
|
|
{
|
|
forSymbol = symbol;
|
|
}
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
GetAllBarPatters(patterns, dirs);
|
|
|
|
//
|
|
// Add(X_BAR_PATTERN_FVG, patterns);
|
|
// Add(forDir, dirs);
|
|
}
|
|
|
|
void RefactorStrategy1OperationalZone(XBoxZone &zone)
|
|
{
|
|
|
|
//
|
|
if (!zone.IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Refine Zone ...
|
|
RefineZone(zone);
|
|
|
|
//
|
|
// SL Refactoring ...
|
|
|
|
//
|
|
XOHCL toBar;
|
|
if (zone.ToBar(toBar))
|
|
{
|
|
//
|
|
int to = zone.ToIndex();
|
|
int from = zone.FromIndex();
|
|
int length = from - to;
|
|
double iValue =
|
|
zone.IsBullish()
|
|
? toBar.FindLowest(length, MODE_LOW)
|
|
: zone.IsBearish()
|
|
? toBar.FindHighest(length, MODE_HIGH)
|
|
: EMPTY_VALUE;
|
|
if (NotEmptyZero(iValue))
|
|
{
|
|
//
|
|
if (zone.IsBullish())
|
|
{
|
|
zone.lower = MathMin(zone.lower, iValue);
|
|
}
|
|
|
|
//
|
|
if (zone.IsBearish())
|
|
{
|
|
zone.upper = MathMax(zone.upper, iValue);
|
|
}
|
|
}
|
|
}
|
|
toBar.Clean();
|
|
}
|
|
|
|
/*
|
|
* Check Recently Pattern Zone is Rejected or not ...
|
|
*
|
|
* @param zone: XBoxZone, Touched Zone ...
|
|
* @param patterns: ENUM_X_BAR_PATTERN, Allowed to Check Patterns ...
|
|
* @param patternsDir: ENUM_X_DIRECTION, Allowed Directions ...
|
|
* @param price: double, a Price to Check Toch or Reject ...
|
|
* @param barIndex: int, Bar Index to Start Checking ...
|
|
* @param loopback: int, Loopback for Pattern Formations ...
|
|
* @param forPeriod: ENUM_TIMEFRAMES, Time Frame to Check Patterns ...
|
|
* @param forDir: ENUM_X_DIRECTION, Directions for Pattern's Formation Check ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasRecentPatternRejected(
|
|
XBoxZone &zone,
|
|
ENUM_X_BAR_PATTERN &patterns[],
|
|
ENUM_X_DIRECTION &patternsDir[],
|
|
int barIndex = 0,
|
|
int loopback = 5,
|
|
ENUM_TIMEFRAMES forPeriod = NULL,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
zone.Clean();
|
|
|
|
//
|
|
// Validate ...
|
|
result =
|
|
HasChild(patterns) &&
|
|
HasChild(patternsDir) &&
|
|
ArraySize(patterns) == ArraySize(patternsDir);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Normalize ...
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
if (IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
|
|
//
|
|
XOHCL bar;
|
|
result = bar.Init(symbol, forPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
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();
|
|
|
|
//
|
|
Copy(
|
|
patterns,
|
|
iConfig.allowedPatterns //
|
|
);
|
|
Copy(
|
|
patternsDir,
|
|
iConfig.allowedDirs //
|
|
);
|
|
|
|
//
|
|
// Looping Back ...
|
|
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);
|
|
isBullish =
|
|
HasChild(iBullishZones) &&
|
|
HasRejected(iBullishIDX, bar, iBullishZones);
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
has = iAnalysis.Count(X_DIRECTION_BEARISH) > 0;
|
|
if (has)
|
|
{
|
|
//
|
|
iAnalysis.GetPatterns(iBearishZones, X_DIRECTION_BEARISH);
|
|
isBearish =
|
|
HasChild(iBearishZones) &&
|
|
HasRejected(iBearishIDX, bar, iBearishZones);
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// Cleanup Resource ...
|
|
iBar.Clean();
|
|
iAnalysis.Clean();
|
|
XClean(iBullishZones);
|
|
XClean(iBearishZones);
|
|
}
|
|
|
|
//
|
|
// Cleanup Resources ...
|
|
bar.Clean();
|
|
iBar.Clean();
|
|
iConfig.Clean();
|
|
iAnalysis.Clean();
|
|
XClean(iBullishZones);
|
|
XClean(iBearishZones);
|
|
|
|
//
|
|
result = zone.IsValid();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
// #endregion
|
|
|
|
// #region Switches ...
|
|
int HasKIFastSwitch(
|
|
XDirectionShift &switches[],
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
XClean(switches);
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool has = false;
|
|
XDirectionShift iShift;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bool hasBullish = kiParser.IsKIFastSwitchedToBullish(i);
|
|
has = hasBullish && isBullish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_FAST),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetKIFast(i),
|
|
kiHelper.GetKIFast(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BULLISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
bool hasBearish = kiParser.IsKIFastSwitchedToBearish(i);
|
|
has = hasBearish && isBearish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_FAST),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetKIFast(i),
|
|
kiHelper.GetKIFast(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(switches);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int HasKISlowSwitch(
|
|
XDirectionShift &switches[],
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
XClean(switches);
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool has = false;
|
|
XDirectionShift iShift;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bool hasBullish = kiParser.IsKISlowSwitchedToBullish(i);
|
|
has = hasBullish && isBullish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_SLOW),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetKISlow(i),
|
|
kiHelper.GetKISlow(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BULLISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
bool hasBearish = kiParser.IsKISlowSwitchedToBearish(i);
|
|
has = hasBearish && isBearish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_SLOW),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetKIFast(i),
|
|
kiHelper.GetKIFast(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(switches);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int HasKISuperSlowSwitch(
|
|
XDirectionShift &switches[],
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
XClean(switches);
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool has = false;
|
|
XDirectionShift iShift;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bool hasBullish = kiParser.IsKISuperSlowSwitchedToBullish(i);
|
|
has = hasBullish && isBullish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_SUPER_SLOW),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetKISuperSlow(i),
|
|
kiHelper.GetKISuperSlow(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BULLISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
bool hasBearish = kiParser.IsKISuperSlowSwitchedToBearish(i);
|
|
has = hasBearish && isBearish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_SUPER_SLOW),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetKIFast(i),
|
|
kiHelper.GetKIFast(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(switches);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int HasKIWaveSwitch(
|
|
XDirectionShift &switches[],
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
XClean(switches);
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool has = false;
|
|
XDirectionShift iShift;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bool hasBullish = kiParser.IsKIWaveSwitchedToBullish(i);
|
|
has = hasBullish && isBullish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_WAVE),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetKIWave(i),
|
|
kiHelper.GetKIWave(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BULLISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
bool hasBearish = kiParser.IsKIWaveSwitchedToBearish(i);
|
|
has = hasBearish && isBearish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_WAVE),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetKIWave(i),
|
|
kiHelper.GetKIWave(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(switches);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int HasMAFastSwitch(
|
|
XDirectionShift &switches[],
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
XClean(switches);
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool has = false;
|
|
XDirectionShift iShift;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bool hasBullish = kiParser.IsMAFastSwitchedToBullish(i);
|
|
has = hasBullish && isBullish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_MA_FAST),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetMAFast(i),
|
|
kiHelper.GetMAFast(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BULLISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
bool hasBearish = kiParser.IsMAFastSwitchedToBearish(i);
|
|
has = hasBearish && isBearish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_MA_FAST),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetMAFast(i),
|
|
kiHelper.GetMAFast(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(switches);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int HasMASlowSwitch(
|
|
XDirectionShift &switches[],
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
XClean(switches);
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool has = false;
|
|
XDirectionShift iShift;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bool hasBullish = kiParser.IsMASlowSwitchedToBullish(i);
|
|
has = hasBullish && isBullish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_MA_SLOW),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetMASlow(i),
|
|
kiHelper.GetMASlow(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BULLISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
bool hasBearish = kiParser.IsMASlowSwitchedToBearish(i);
|
|
has = hasBearish && isBearish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_MA_SLOW),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetMAFast(i),
|
|
kiHelper.GetMAFast(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(switches);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int HasMASuperSlowSwitch(
|
|
XDirectionShift &switches[],
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
XClean(switches);
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool has = false;
|
|
XDirectionShift iShift;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bool hasBullish = kiParser.IsMASuperSlowSwitchedToBullish(i);
|
|
has = hasBullish && isBullish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_MA_SUPER_SLOW),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetMASuperSlow(i),
|
|
kiHelper.GetMASuperSlow(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BULLISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
bool hasBearish = kiParser.IsMASuperSlowSwitchedToBearish(i);
|
|
has = hasBearish && isBearish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_MA_SUPER_SLOW),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetMAFast(i),
|
|
kiHelper.GetMAFast(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(switches);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int HasMACrossedSwitch(
|
|
XDirectionShift &switches[],
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
XClean(switches);
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool has = false;
|
|
XDirectionShift iShift;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bool hasBullish = kiParser.IsMACrossoverSwitchedToBullish(i);
|
|
has = hasBullish && isBullish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_MA_CROSS),
|
|
GetBarTime(symbol, period, i),
|
|
MathMin(kiHelper.GetMAFast(i), kiHelper.GetMASlow(i)),
|
|
MathMin(kiHelper.GetMAFast(i + 1), kiHelper.GetMASlow(i + 1)),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BULLISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
bool hasBearish = kiParser.IsMACrossoverSwitchedToBearish(i);
|
|
has = hasBearish && isBearish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_MA_CROSS),
|
|
GetBarTime(symbol, period, i),
|
|
MathMin(kiHelper.GetMAFast(i), kiHelper.GetMASlow(i)),
|
|
MathMin(kiHelper.GetMAFast(i + 1), kiHelper.GetMASlow(i + 1)),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(switches);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int HasATRVolatilitySwitch(
|
|
XDirectionShift &switches[],
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
XClean(switches);
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool has = false;
|
|
XDirectionShift iShift;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
// Bullish ...
|
|
bool hasBullish = kiParser.IsVolatilitySwitchdToHigh(i);
|
|
has = hasBullish && isBullish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_ATR),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetATR(i),
|
|
kiHelper.GetATR(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BULLISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish ...
|
|
bool hasBearish = kiParser.IsVolatilitySwitchdToLow(i);
|
|
has = hasBearish && isBearish;
|
|
if (has)
|
|
{
|
|
//
|
|
iShift.Clean();
|
|
has = iShift.Init(
|
|
ToXString(X121_XKI_ATR),
|
|
GetBarTime(symbol, period, i),
|
|
kiHelper.GetATR(i),
|
|
kiHelper.GetATR(i + 1),
|
|
symbol,
|
|
period,
|
|
X_DIRECTION_BEARISH //
|
|
);
|
|
if (has)
|
|
{
|
|
//
|
|
AddIfNotExists(
|
|
iShift,
|
|
switches //
|
|
);
|
|
|
|
//
|
|
iShift.Clean();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(switches);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
// #endregion
|
|
|
|
// #region Peak and Vale ...
|
|
// TODO: Implement Root of Changes when IsPeakOverLast or IsValeUnderLast Happens ...
|
|
// #endregion
|
|
|
|
// #region Rejecteds ...
|
|
bool IsKIFastRejected(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
if (!IsXValid(forSymbol))
|
|
{
|
|
forSymbol = symbol;
|
|
}
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
XOHCL bar;
|
|
result =
|
|
kiParser.IsValid() &&
|
|
bar.Init(forSymbol, forPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double iValue = kiHelper.GetKIFast(barIndex);
|
|
|
|
//
|
|
bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false);
|
|
bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false);
|
|
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsKISlowRejected(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
if (!IsXValid(forSymbol))
|
|
{
|
|
forSymbol = symbol;
|
|
}
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
XOHCL bar;
|
|
result =
|
|
kiParser.IsValid() &&
|
|
bar.Init(forSymbol, forPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double iValue = kiHelper.GetKISlow(barIndex);
|
|
|
|
//
|
|
bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false);
|
|
bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false);
|
|
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsKISuperSlowRejected(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
if (!IsXValid(forSymbol))
|
|
{
|
|
forSymbol = symbol;
|
|
}
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
XOHCL bar;
|
|
result =
|
|
kiParser.IsValid() &&
|
|
bar.Init(forSymbol, forPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double iValue = kiHelper.GetKISuperSlow(barIndex);
|
|
|
|
//
|
|
bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false);
|
|
bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false);
|
|
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsKIUpperRejected(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
if (!IsXValid(forSymbol))
|
|
{
|
|
forSymbol = symbol;
|
|
}
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
XOHCL bar;
|
|
result =
|
|
kiParser.IsValid() &&
|
|
bar.Init(forSymbol, forPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double iValue = kiHelper.GetKIUpper(barIndex);
|
|
|
|
//
|
|
bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false);
|
|
bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false);
|
|
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsKILowerRejected(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
if (!IsXValid(forSymbol))
|
|
{
|
|
forSymbol = symbol;
|
|
}
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
XOHCL bar;
|
|
result =
|
|
kiParser.IsValid() &&
|
|
bar.Init(forSymbol, forPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double iValue = kiHelper.GetKILower(barIndex);
|
|
|
|
//
|
|
bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false);
|
|
bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false);
|
|
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsMAFastRejected(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
if (!IsXValid(forSymbol))
|
|
{
|
|
forSymbol = symbol;
|
|
}
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
XOHCL bar;
|
|
result =
|
|
kiParser.IsValid() &&
|
|
bar.Init(forSymbol, forPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double iValue = kiHelper.GetMAFast(barIndex);
|
|
|
|
//
|
|
bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false);
|
|
bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false);
|
|
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsMASlowRejected(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
if (!IsXValid(forSymbol))
|
|
{
|
|
forSymbol = symbol;
|
|
}
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
XOHCL bar;
|
|
result =
|
|
kiParser.IsValid() &&
|
|
bar.Init(forSymbol, forPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double iValue = kiHelper.GetMASlow(barIndex);
|
|
|
|
//
|
|
bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false);
|
|
bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false);
|
|
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsMASuperSlowRejected(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
if (!IsXValid(forSymbol))
|
|
{
|
|
forSymbol = symbol;
|
|
}
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
XOHCL bar;
|
|
result =
|
|
kiParser.IsValid() &&
|
|
bar.Init(forSymbol, forPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double iValue = kiHelper.GetMASuperSlow(barIndex);
|
|
|
|
//
|
|
bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false);
|
|
bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false);
|
|
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsPrevPeakRejected(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
if (!IsXValid(forSymbol))
|
|
{
|
|
forSymbol = symbol;
|
|
}
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
XOHCL bar;
|
|
result =
|
|
kiParser.IsValid() &&
|
|
bar.Init(forSymbol, forPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double iValue = kiHelper.GetPeak(barIndex + 1);
|
|
|
|
//
|
|
bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false);
|
|
bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false);
|
|
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
bool IsPrevValeRejected(
|
|
ENUM_X_DIRECTION &dir,
|
|
int barIndex = 0,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
dir = X_DIRECTION_NONE;
|
|
if (!IsXValid(forSymbol))
|
|
{
|
|
forSymbol = symbol;
|
|
}
|
|
if (!IsXValid(forPeriod))
|
|
{
|
|
forPeriod = period;
|
|
}
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
XOHCL bar;
|
|
result =
|
|
kiParser.IsValid() &&
|
|
bar.Init(forSymbol, forPeriod, barIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double iValue = kiHelper.GetVale(barIndex + 1);
|
|
|
|
//
|
|
bool isBullish = bar.IsRejected(iValue, X_DIRECTION_BULLISH, false, false);
|
|
bool isBearish = bar.IsRejected(iValue, X_DIRECTION_BEARISH, false, false);
|
|
|
|
//
|
|
dir =
|
|
isBullish
|
|
? X_DIRECTION_BULLISH
|
|
: isBearish
|
|
? X_DIRECTION_BEARISH
|
|
: X_DIRECTION_NONE;
|
|
|
|
//
|
|
result = HasDirection(dir);
|
|
|
|
//
|
|
bar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
// #endregion
|
|
|
|
// #region Counters ...
|
|
int CountKIFastRejects(
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool is = false;
|
|
bool hasBullish = false;
|
|
bool hasBearish = false;
|
|
ENUM_X_DIRECTION tmpDir;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
is = IsKIFastRejected(
|
|
tmpDir,
|
|
i,
|
|
forSymbol,
|
|
forPeriod //
|
|
);
|
|
hasBullish = is && IsXBullish(tmpDir);
|
|
hasBearish = is && IsXBearish(tmpDir);
|
|
|
|
//
|
|
if ((isBullish && hasBullish) ||
|
|
(isBearish && hasBearish))
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int CountKISlowRejects(
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool is = false;
|
|
bool hasBullish = false;
|
|
bool hasBearish = false;
|
|
ENUM_X_DIRECTION tmpDir;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
is = IsKISlowRejected(
|
|
tmpDir,
|
|
i,
|
|
forSymbol,
|
|
forPeriod //
|
|
);
|
|
hasBullish = is && IsXBullish(tmpDir);
|
|
hasBearish = is && IsXBearish(tmpDir);
|
|
|
|
//
|
|
if ((isBullish && hasBullish) ||
|
|
(isBearish && hasBearish))
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int CountKISuperSlowRejects(
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool is = false;
|
|
bool hasBullish = false;
|
|
bool hasBearish = false;
|
|
ENUM_X_DIRECTION tmpDir;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
is = IsKISuperSlowRejected(
|
|
tmpDir,
|
|
i,
|
|
forSymbol,
|
|
forPeriod //
|
|
);
|
|
hasBullish = is && IsXBullish(tmpDir);
|
|
hasBearish = is && IsXBearish(tmpDir);
|
|
|
|
//
|
|
if ((isBullish && hasBullish) ||
|
|
(isBearish && hasBearish))
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int CountKIUpperRejects(
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool is = false;
|
|
bool hasBullish = false;
|
|
bool hasBearish = false;
|
|
ENUM_X_DIRECTION tmpDir;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
is = IsKIUpperRejected(
|
|
tmpDir,
|
|
i,
|
|
forSymbol,
|
|
forPeriod //
|
|
);
|
|
hasBullish = is && IsXBullish(tmpDir);
|
|
hasBearish = is && IsXBearish(tmpDir);
|
|
|
|
//
|
|
if ((isBullish && hasBullish) ||
|
|
(isBearish && hasBearish))
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int CountKILowerRejects(
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool is = false;
|
|
bool hasBullish = false;
|
|
bool hasBearish = false;
|
|
ENUM_X_DIRECTION tmpDir;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
is = IsKILowerRejected(
|
|
tmpDir,
|
|
i,
|
|
forSymbol,
|
|
forPeriod //
|
|
);
|
|
hasBullish = is && IsXBullish(tmpDir);
|
|
hasBearish = is && IsXBearish(tmpDir);
|
|
|
|
//
|
|
if ((isBullish && hasBullish) ||
|
|
(isBearish && hasBearish))
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int CountMAFastRejects(
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool is = false;
|
|
bool hasBullish = false;
|
|
bool hasBearish = false;
|
|
ENUM_X_DIRECTION tmpDir;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
is = IsMAFastRejected(
|
|
tmpDir,
|
|
i,
|
|
forSymbol,
|
|
forPeriod //
|
|
);
|
|
hasBullish = is && IsXBullish(tmpDir);
|
|
hasBearish = is && IsXBearish(tmpDir);
|
|
|
|
//
|
|
if ((isBullish && hasBullish) ||
|
|
(isBearish && hasBearish))
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int CountMASlowRejects(
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool is = false;
|
|
bool hasBullish = false;
|
|
bool hasBearish = false;
|
|
ENUM_X_DIRECTION tmpDir;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
is = IsMASlowRejected(
|
|
tmpDir,
|
|
i,
|
|
forSymbol,
|
|
forPeriod //
|
|
);
|
|
hasBullish = is && IsXBullish(tmpDir);
|
|
hasBearish = is && IsXBearish(tmpDir);
|
|
|
|
//
|
|
if ((isBullish && hasBullish) ||
|
|
(isBearish && hasBearish))
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int CountMASuperSlowRejects(
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool is = false;
|
|
bool hasBullish = false;
|
|
bool hasBearish = false;
|
|
ENUM_X_DIRECTION tmpDir;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
is = IsMASuperSlowRejected(
|
|
tmpDir,
|
|
i,
|
|
forSymbol,
|
|
forPeriod //
|
|
);
|
|
hasBullish = is && IsXBullish(tmpDir);
|
|
hasBearish = is && IsXBearish(tmpDir);
|
|
|
|
//
|
|
if ((isBullish && hasBullish) ||
|
|
(isBearish && hasBearish))
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int CountPrevPeakRejects(
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool is = false;
|
|
bool hasBullish = false;
|
|
bool hasBearish = false;
|
|
ENUM_X_DIRECTION tmpDir;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
is = IsPrevPeakRejected(
|
|
tmpDir,
|
|
i,
|
|
forSymbol,
|
|
forPeriod //
|
|
);
|
|
hasBullish = is && IsXBullish(tmpDir);
|
|
hasBearish = is && IsXBearish(tmpDir);
|
|
|
|
//
|
|
if ((isBullish && hasBullish) ||
|
|
(isBearish && hasBearish))
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
int CountPrevValeRejects(
|
|
int barIndex = 0,
|
|
int loopback = 10,
|
|
ENUM_X_DIRECTION forDir = X_DIRECTION_NONE,
|
|
string forSymbol = NULL,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
loopback = NormalizeInt(loopback, 2);
|
|
barIndex = kiParser.NormalizeBarIndex(barIndex);
|
|
|
|
//
|
|
bool isBullish = !HasDirection(forDir) || IsXBullish(forDir);
|
|
bool isBearish = !HasDirection(forDir) || IsXBearish(forDir);
|
|
|
|
//
|
|
bool is = false;
|
|
bool hasBullish = false;
|
|
bool hasBearish = false;
|
|
ENUM_X_DIRECTION tmpDir;
|
|
for (int i = barIndex; i < barIndex + loopback; i++)
|
|
{
|
|
//
|
|
is = IsPrevValeRejected(
|
|
tmpDir,
|
|
i,
|
|
forSymbol,
|
|
forPeriod //
|
|
);
|
|
hasBullish = is && IsXBullish(tmpDir);
|
|
hasBearish = is && IsXBearish(tmpDir);
|
|
|
|
//
|
|
if ((isBullish && hasBullish) ||
|
|
(isBearish && hasBearish))
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
// #endregion
|
|
// #endregion |