adding provided strategy 1 signalling conditions ...

This commit is contained in:
2026-02-25 23:24:45 +03:30
parent 887d44511a
commit 45b7586593
2 changed files with 2460 additions and 267 deletions
File diff suppressed because it is too large Load Diff
@@ -533,13 +533,13 @@ class XCX121XKIStrategy1Signaller : public XCX121XKIBaseSignaller
//
// Signaller Flags ...
bool useSignaller1 = false;
bool useSignaller1 = true;
bool useSignaller2 = false;
bool useSignaller3 = false;
bool useSignaller4 = false;
bool useSignaller5 = false;
bool useSignaller6 = false;
bool useSignaller7 = true;
bool useSignaller7 = false;
//
XBoxZone tmpZone;
@@ -975,9 +975,14 @@ class XCX121XKIStrategy1Signaller : public XCX121XKIBaseSignaller
}
// #region Custom Signal Strategies ...
//+------------------------------------------------------------------+
//| X121XKI Strategy 1: POI + KI Confluence |
//| Concept: Order Block/FVG + KI Trend Confirmation |
//+------------------------------------------------------------------+
/**
* Check Bar Has Signal Based on Strategy 1 ...
* POI ...
* POI + KI Confluence ...
*
* @param bar: XOHCL, reference to Bar ...
* @param zone: XBoxZone, reference to holds affected zone ...
@@ -1002,359 +1007,669 @@ class XCX121XKIStrategy1Signaller : public XCX121XKIBaseSignaller
dir = X_DIRECTION_NONE;
//
result = bar.IsValid();
result = bar.IsValid() &&
kiParser.IsValid();
if (!result)
{
return result;
}
//
// Configuration ...
double score = 0;
bool isBullish = false;
bool isBearish = false;
int barIndex = bar.Index() + 1;
double points = GetPoints(symbol);
int minOBPoints = 30; // Minimum Order Block size in points
int minFVGPoints = 20; // Minimum FVG size in points
double minScore = 15.0; // Minimum score for signal
int kiConfirmationBars = 3; // Bars for KI confirmation
// #region KI Trend Confirmation ...
//
// Check KI Fast Trend ...
bool kiFastBullish = kiParser.IsKIFastBullish(barIndex);
bool kiFastBearish = kiParser.IsKIFastBearish(barIndex);
//
// TEST ...
// Check KI Slow Trend ...
bool kiSlowBullish = kiParser.IsKISlowBullish(barIndex);
bool kiSlowBearish = kiParser.IsKISlowBearish(barIndex);
//
if (kiParser.IsKIFastBullish(barIndex))
// Check KI Super Slow Trend ...
bool kiSuperSlowBullish = kiParser.IsKISlowBullish(barIndex);
bool kiSuperSlowBearish = kiParser.IsKISlowBearish(barIndex);
//
bool kiWaveBullish = kiParser.IsKIWaveSwitchedToBullish(barIndex);
bool kiWaveBearish = kiParser.IsKIWaveSwitchedToBearish(barIndex);
//
bool priceAboveKIFast = bar.close > kiHelper.GetKIFast(barIndex);
bool priceBelowKIFast = bar.close < kiHelper.GetKIFast(barIndex);
// #endregion
// #region RSI Momentum Confirmation ...
//
// Check RSI State ...
bool rsiBullish = kiParser.IsRSISwitchedToBullish(barIndex, 55, 2);
bool rsiBearish = kiParser.IsRSISwitchedToBearish(barIndex, 45, 2);
//
// Check RSI Overbought/Oversold ...
bool rsiOverbought = kiParser.IsRSIOverbought(barIndex, 70, 2);
bool rsiOversold = kiParser.IsRSIOversold(barIndex, 30, 2);
//
// Check RSI Divergence (Price vs RSI) ...
bool rsiBullishDivergence = false;
bool rsiBearishDivergence = false;
//
// Simple Divergence Check (can be enhanced) ...
if (barIndex + 5 < bar.TotalBars())
{
DebugBreak();
//
double currentRSI = kiHelper.GetRSI(barIndex);
double previousRSI = kiHelper.GetRSI(barIndex + 5);
double currentLow = bar.low;
double previousLow = bar.FindLowest(5, MODE_LOW);
double currentHigh = bar.high;
double previousHigh = bar.FindHighest(5, MODE_HIGH);
//
// Bullish Divergence ...
rsiBullishDivergence = (currentLow < previousLow) && (currentRSI > previousRSI);
//
// Bearish Divergence ...
rsiBearishDivergence = (currentHigh > previousHigh) && (currentRSI < previousRSI);
}
// #endregion
// //
// bool hasTrend =
// kiParser.HasCompositeTrend(
// score,
// dir,
// barIndex,
// 20, // Required Score ...
// 2, // Tolerance ...
// X_PRICE_CLOSE,
// 55,
// 45,
// 70,
// 30 //
// );
// if (hasTrend && IsXBearish(dir))
// {
// DebugBreak();
// }
// #region ATR Volatility Check ...
//
// Check Volatility Expansion ...
bool volatilityHigh = kiParser.IsVolatilityHigh(barIndex);
bool volatilitySwitchedHigh = kiParser.IsVolatilitySwitchdToHigh(barIndex);
//
return false;
// Check ATR Breakout ...
bool atrBreakoutUp = kiParser.IsATRBreakoutUp(barIndex, X_PRICE_CLOSE);
bool atrBreakoutDown = kiParser.IsATRBreakoutDown(barIndex, X_PRICE_CLOSE);
// #endregion
// #region POI Detection (Order Blocks & FVG) ...
//
// Detect Order Blocks ...
XBoxZone bullishOBs[];
XBoxZone bearishOBs[];
//
// Initialize Indexed Bar ...
XOHCL iBar;
result = iBar.Init(bar.symbol, bar.period, barIndex);
if (!result)
int bullishOBCount = poiDetector.CollectOBs(bar, bullishOBs, 5, 10, 100);
int bearishOBCount = poiDetector.CollectOBs(bar, bearishOBs, 5, 10, 100);
//
// Detect Fair Value Gaps ...
XBoxZone bullishFVGs[];
XBoxZone bearishFVGs[];
//
int bullishFVGCount = poiDetector.CollectFVGs(bar, bullishFVGs, 5, 10, 100);
int bearishFVGCount = poiDetector.CollectFVGs(bar, bearishFVGs, 5, 10, 100);
//
// Validate OB/FVG Size ...
XBoxZone validBullishOBs[];
XBoxZone validBearishOBs[];
XBoxZone validBullishFVGs[];
XBoxZone validBearishFVGs[];
//
// Filter Bullish OBs ...
for (int i = 0; i < bullishOBCount; i++)
{
return result;
//
double obRange = (bullishOBs[i].upper - bullishOBs[i].lower) / points;
if (obRange >= minOBPoints && !IsXValid(bullishOBs[i].breakAt))
{
AddIfNotExists(bullishOBs[i], validBullishOBs);
}
}
//
XBoxZone swingLow;
// Filter Bearish OBs ...
for (int i = 0; i < bearishOBCount; i++)
{
//
double obRange = (bearishOBs[i].upper - bearishOBs[i].lower) / points;
if (obRange >= minOBPoints && !IsXValid(bearishOBs[i].breakAt))
{
AddIfNotExists(bearishOBs[i], validBearishOBs);
}
}
//
// Filter Bullish FVGs ...
for (int i = 0; i < bullishFVGCount; i++)
{
//
double fvgRange = (bullishFVGs[i].upper - bullishFVGs[i].lower) / points;
if (fvgRange >= minFVGPoints && !IsXValid(bullishFVGs[i].breakAt))
{
AddIfNotExists(bullishFVGs[i], validBullishFVGs);
}
}
//
// Filter Bearish FVGs ...
for (int i = 0; i < bearishFVGCount; i++)
{
//
double fvgRange = (bearishFVGs[i].upper - bearishFVGs[i].lower) / points;
if (fvgRange >= minFVGPoints && !IsXValid(bearishFVGs[i].breakAt))
{
AddIfNotExists(bearishFVGs[i], validBearishFVGs);
}
}
// #endregion
// #region Liquidity Check ...
//
// Detect Recent Swings (Liquidity Pools) ...
XBoxZone swingHigh;
ENUM_X_DIRECTION patternsDir[];
ENUM_X_BAR_PATTERN patterns[];
poiDetector.FillStrategy1Patterns(
patterns,
patternsDir //
);
XBoxZone swingLow;
//
// Reading Swings ...
poiDetector.DetectRecentSwings(
swingHigh,
swingLow,
barIndex //
);
poiDetector.DetectRecentSwings(swingHigh, swingLow, barIndex, 50, 500, period, true);
//
// Reading Order Flow ...
// Check if Liquidity was Swept ...
bool liquiditySweptHigh = false;
bool liquiditySweptLow = false;
//
// Bullish Order Flow ...
XBoxZone bullishOrderFlow[];
int bullishOrderFlowRejectdIDX = -1;
poiDetector.HasOrderFlow(bullishOrderFlow, barIndex, 4, X_DIRECTION_BULLISH, 15);
//
// Bearish Order Flow ...
XBoxZone bearishOrderFlow[];
int bearishOrderFlowRejectdIDX = -1;
poiDetector.HasOrderFlow(bearishOrderFlow, barIndex, 4, X_DIRECTION_BEARISH, 15);
//
// Base Conditions ...
//
isBullish =
IsTFBullishPattern(barIndex, PERIOD_M1) &&
IsTFBullishPattern(barIndex, PERIOD_M5) &&
IsTFBullishPattern(barIndex, iBar.period) &&
HasRejected(
bullishOrderFlowRejectdIDX,
iBar,
bullishOrderFlow //
) &&
poiDetector.HasRecentPatternRejected(
zone,
patterns,
patternsDir,
barIndex,
3, // Loopback ..
iBar.period,
X_DIRECTION_BULLISH //
);
if (!isBullish)
if (swingHigh.IsValid())
{
//
isBearish =
IsTFBearishPattern(barIndex, PERIOD_M1) &&
IsTFBearishPattern(barIndex, PERIOD_M5) &&
IsTFBearishPattern(barIndex, iBar.period) &&
HasRejected(
bearishOrderFlowRejectdIDX,
iBar,
bearishOrderFlow //
) &&
poiDetector.HasRecentPatternRejected(
zone,
patterns,
patternsDir,
barIndex,
3, // Loopback ..
iBar.period,
X_DIRECTION_BEARISH //
);
liquiditySweptHigh = bar.high > swingHigh.upper;
}
//
// Summarize Result ...
result = isBullish || isBearish;
//
// Count Touches ...
// int bullishTouches = 0;
// int bearishTouches = 0;
// if (result)
// {
// //
// kiParser.CountTouches(
// bullishTouches,
// bearishTouches,
// barIndex,
// 4 // Loopback ...
// );
// //
// isBullish =
// isBullish &&
// bullishTouches >= bearishTouches;
// //
// isBearish =
// isBearish &&
// bearishTouches >= bullishTouches;
// //
// // Summarize Result ...
// result = isBullish || isBearish;
// if (!result)
// {
// //
// isBullish = false;
// isBearish = false;
// }
// //
// if (bullishTouches > 0 || bearishTouches > 0)
// {
// // DebugBreak();
// }
// }
//
if (!result)
if (swingLow.IsValid())
{
//
iBar.Clean();
liquiditySweptLow = bar.low < swingLow.lower;
}
// #endregion
//
return result;
// #region Multi-Timeframe Confirmation ...
//
// Check Lower Timeframe Alignment ...
bool isLowerTFBullish = IsTFBullishPattern(barIndex, PERIOD_M1);
bool isLowerTFBearish = IsTFBearishPattern(barIndex, PERIOD_M1);
//
// Check Higher Timeframe Alignment ...
bool isHigherTFBullish = IsTFBullishPattern(barIndex, GetNearestPeriod(period));
bool isHigherTFBearish = IsTFBearishPattern(barIndex, GetNearestPeriod(period));
// #endregion
//
//
//
// #region Bullish Signal Logic ...
//
// Calculate Bullish Score ...
double bullishScore = 0;
//
// KI Trend Alignment (Max 5 points) ...
if (kiFastBullish)
{
bullishScore += 1;
}
if (kiSlowBullish)
{
bullishScore += 1;
}
//
// Do Directional Validation ...
if (result)
// HTF bias more important
if (kiSuperSlowBullish)
{
//
poiDetector.RefactorStrategy1OperationalZone(zone);
bullishScore += 2;
}
//
// Bullish ...
if (isBullish)
if (priceAboveKIFast)
{
bullishScore += 1;
}
//
// KI Wave Momentum (Max 2 points) ...
if (kiWaveBullish)
{
bullishScore += 2;
}
//
// RSI Confirmation (Max 3 points) ...
if (rsiBullish)
{
bullishScore += 2;
}
//
// Divergence is strong signal ...
if (rsiBullishDivergence)
{
bullishScore += 3;
}
if (rsiOversold)
{
bullishScore += 1;
}
//
// Volatility (Max 2 points) ...
if (volatilityHigh)
{
bullishScore += 1;
}
if (volatilitySwitchedHigh)
{
bullishScore += 1;
}
//
// POI Presence (Max 5 points) ...
if (ArraySize(validBullishOBs) > 0)
{
bullishScore += 3;
}
if (ArraySize(validBullishFVGs) > 0)
{
bullishScore += 2;
}
//
// Liquidity Sweep (Max 3 points) ...
if (liquiditySweptLow)
{
bullishScore += 3;
}
//
// MTF Alignment (Max 2 points) ...
if (isLowerTFBullish)
{
bullishScore += 1;
}
if (isHigherTFBullish)
{
bullishScore += 1;
}
//
// Check Bullish Conditions ...
isBullish = (bullishScore >= minScore) &&
(ArraySize(validBullishOBs) > 0 ||
ArraySize(validBullishFVGs) > 0) &&
(kiFastBullish || kiWaveBullish);
// #endregion
// #region Bearish Signal Logic ...
//
// Calculate Bearish Score ...
double bearishScore = 0;
//
// KI Trend Alignment (Max 5 points) ...
if (kiFastBearish)
{
bearishScore += 1;
}
if (kiSlowBearish)
{
bearishScore += 1;
}
if (kiSuperSlowBearish)
{
bearishScore += 2;
}
if (priceBelowKIFast)
{
bearishScore += 1;
}
//
// KI Wave Momentum (Max 2 points) ...
if (kiWaveBearish)
{
bearishScore += 2;
}
//
// RSI Confirmation (Max 3 points) ...
if (rsiBearish)
{
bearishScore += 2;
}
if (rsiBearishDivergence)
{
bearishScore += 3;
}
if (rsiOverbought)
{
bearishScore += 1;
}
//
// Volatility (Max 2 points) ...
if (volatilityHigh)
{
bearishScore += 1;
}
if (volatilitySwitchedHigh)
{
bearishScore += 1;
}
//
// POI Presence (Max 5 points) ...
if (ArraySize(validBearishOBs) > 0)
{
bearishScore += 3;
}
if (ArraySize(validBearishFVGs) > 0)
{
bearishScore += 2;
}
//
// Liquidity Sweep (Max 3 points) ...
if (liquiditySweptHigh)
{
bearishScore += 3;
}
//
// MTF Alignment (Max 2 points) ...
if (isLowerTFBearish)
{
bearishScore += 1;
}
if (isHigherTFBearish)
{
bearishScore += 1;
}
//
// Check Bearish Conditions ...
isBearish = (bearishScore >= minScore) &&
(ArraySize(validBearishOBs) > 0 ||
ArraySize(validBearishFVGs) > 0) &&
(kiFastBearish || kiWaveBearish);
// #endregion
// #region Signal Generation ...
//
// Ensure Only One Direction ...
if (isBullish && isBearish)
{
// Use higher score to determine direction ...
if (bullishScore > bearishScore)
{
// //
// isBullish =
// isBullish &&
// isLowerTFBullish &&
// isCandlestickBullish;
isBearish = false;
}
//
// Bearish ...
if (isBearish)
else if (bearishScore > bullishScore)
{
// //
// isBearish =
// isBearish &&
// isLowerTFBearish &&
// isCandlestickBearish;
isBullish = false;
}
//
result = isBullish || isBearish;
if (!result)
else
{
//
// Same score, no signal ...
isBullish = false;
isBearish = false;
}
}
//
// Draws ...
bool draw = true;
if (draw && result)
// Generate Bullish Signal ...
if (isBullish)
{
//
int drawn = 0;
dir = X_DIRECTION_BULLISH;
//
poiDrawer.drawnObjects.Clear();
// Select Best POI (Youngest Valid OB or FVG) ...
XBoxZone selectedPOI;
//
XPOIDrawConfig config;
config.Default();
int obIdx = GetYoungest(validBullishOBs);
int fvgIdx = GetYoungest(validBullishFVGs);
//
if (zone.IsValid())
if (IsValidIndex(obIdx) && IsValidIndex(fvgIdx))
{
//
drawn++;
// Choose the one closer to current price ...
double obDistance = bar.close - validBullishOBs[obIdx].upper;
double fvgDistance = bar.close - validBullishFVGs[fvgIdx].upper;
//
config.zonesWidth = 3;
config.bullishColor = clrYellow;
config.bearishColor = clrOrange;
//
poiDrawer.DrawZone(zone, config);
//
config.Default();
selectedPOI = (obDistance < fvgDistance) ? validBullishOBs[obIdx] : validBullishFVGs[fvgIdx];
}
else if (IsValidIndex(obIdx))
{
selectedPOI = validBullishOBs[obIdx];
}
else if (IsValidIndex(fvgIdx))
{
selectedPOI = validBullishFVGs[fvgIdx];
}
//
if (swingLow.IsValid())
// Validate Selected POI ...
if (selectedPOI.IsValid())
{
//
drawn++;
poiDrawer.DrawZone(swingLow, config);
}
zone = selectedPOI;
zone.type = "S1_POI_KI";
//
if (swingHigh.IsValid())
{
//
drawn++;
poiDrawer.DrawZone(swingHigh, config);
}
// Calculate Targets ...
double entry = GetEntry(symbol, dir);
double risk = MathAbs(entry - zone.lower);
double reward = risk * defaultSignalR2R;
//
if (HasChild(bullishOrderFlow))
{
//
drawn += ArraySize(bullishOrderFlow);
poiDrawer.DrawZones(bullishOrderFlow, config);
}
// TP1: 1:1 R:R ...
XTarget tp1;
tp1.target = entry + risk;
tp1.volumeMultiplier = 0.5;
tp1.doRF = true;
tp1.doRFOnEntry = false;
AddRef(tp1, targets);
//
if (HasChild(bearishOrderFlow))
{
//
drawn += ArraySize(bearishOrderFlow);
poiDrawer.DrawZones(bearishOrderFlow, config);
}
// TP2: 1:2 R:R ...
XTarget tp2;
tp2.target = entry + (risk * 2);
tp2.volumeMultiplier = 0.5;
tp2.doRF = false;
tp2.doRFOnEntry = false;
AddRef(tp2, targets);
//
if (drawn > 0)
{
DebugBreak();
return false;
//
// TP3: Next Liquidity (Swing High) ...
if (swingHigh.IsValid())
{
//
XTarget tp3;
tp3.target = swingHigh.upper + (10 * points);
tp3.volumeMultiplier = 1.0;
tp3.doRF = false;
tp3.doRFOnEntry = false;
AddRef(tp3, targets);
}
}
//
config.Clean();
}
//
// Check and Prepare Direction ...
dir =
isBullish
? X_DIRECTION_BULLISH
: isBearish ? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
result = result &&
HasDirection(dir);
// Generate Bearish Signal ...
else if (isBearish)
{
//
dir = X_DIRECTION_BEARISH;
//
// Select Best POI (Youngest Valid OB or FVG) ...
XBoxZone selectedPOI;
//
int obIdx = GetYoungest(validBearishOBs);
int fvgIdx = GetYoungest(validBearishFVGs);
//
if (IsValidIndex(obIdx) && IsValidIndex(fvgIdx))
{
//
// Choose the one closer to current price ...
double obDistance = zone.lower - bar.close;
double fvgDistance = zone.lower - bar.close;
//
selectedPOI = (obDistance < fvgDistance) ? validBearishOBs[obIdx] : validBearishFVGs[fvgIdx];
}
else if (IsValidIndex(obIdx))
{
selectedPOI = validBearishOBs[obIdx];
}
else if (IsValidIndex(fvgIdx))
{
selectedPOI = validBearishFVGs[fvgIdx];
}
//
// Validate Selected POI ...
if (selectedPOI.IsValid())
{
//
zone = selectedPOI;
zone.type = "S1_POI_KI";
//
// Calculate Targets ...
double entry = GetEntry(symbol, dir);
double risk = MathAbs(zone.upper - entry);
double reward = risk * defaultSignalR2R;
//
// TP1: 1:1 R:R ...
XTarget tp1;
tp1.target = entry - risk;
tp1.volumeMultiplier = 0.5;
tp1.doRF = true;
tp1.doRFOnEntry = false;
AddRef(tp1, targets);
//
// TP2: 1:2 R:R ...
XTarget tp2;
tp2.target = entry - (risk * 2);
tp2.volumeMultiplier = 0.5;
tp2.doRF = false;
tp2.doRFOnEntry = false;
AddRef(tp2, targets);
//
// TP3: Next Liquidity (Swing Low) ...
if (swingLow.IsValid())
{
//
XTarget tp3;
tp3.target = swingLow.lower - (10 * points);
tp3.volumeMultiplier = 1.0;
tp3.doRF = false;
tp3.doRFOnEntry = false;
AddRef(tp3, targets);
}
}
}
// #endregion
// #region Validation & Risk Management ...
//
// Validate Signal ...
result = zone.IsValid() && HasDirection(dir) && HasChild(targets);
//
// Check Max Allowed Risk ...
if (result && maxAllowedRiskDistance > 0)
{
//
double riskInPoints = 0;
if (dir == X_DIRECTION_BULLISH)
{
riskInPoints = MathAbs(zone.GetDirectionalPrice() - zone.GetInDirectionalPrice()) / points;
}
else
{
riskInPoints = MathAbs(zone.GetInDirectionalPrice() - zone.GetDirectionalPrice()) / points;
}
//
if (riskInPoints > maxAllowedRiskDistance)
{
//
result = false;
zone.Clean();
XClean(targets);
dir = X_DIRECTION_NONE;
}
}
// #endregion
//
// Optional: Debug Break for Testing ...
if (result)
{
//
// Prepare Zone ...
double entry = GetEntry(iBar.symbol, dir);
//
double upper = isBullish
? entry
: zone.upper;
double lower = isBullish
? zone.lower
: entry;
datetime to = bar.time;
datetime from = isBullish
? zone.from
: zone.from;
result = zone.Init(
iBar.symbol,
iBar.period,
upper,
lower,
from,
to,
dir,
"XS1" //
);
Print("Strategy 1 Signal Detected:");
Print(" Direction: ", ToXString(dir));
Print(" Bullish Score: ", bullishScore);
Print(" Bearish Score: ", bearishScore);
Print(" POI Type: ", zone.type);
Print(" Targets Count: ", ArraySize(targets));
DebugBreak();
}
//
// Cleanup Resources ...
iBar.Clean();
swingLow.Clean();
XClean(patterns);
swingHigh.Clean();
XClean(patternsDir);
XClean(bullishOrderFlow);
XClean(bearishOrderFlow);
//
result =
result &&
zone.IsValid() &&
HasDirection(dir);
XClean(bullishOBs);
XClean(bearishOBs);
XClean(bullishFVGs);
XClean(bearishFVGs);
XClean(validBullishOBs);
XClean(validBearishOBs);
XClean(validBullishFVGs);
XClean(validBearishFVGs);
//
return result;