Files
MQL5Data/X121XKIEA/Classes/x-saherelm.x121.xki.signaller.class.mq5
T
2025-12-31 13:49:57 +03:30

1342 lines
31 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class
// -------------------------------------------------
// Name: XCX121XKISignaller ...
// Description: X121XKI Signaller Class ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://saherelm.ir"
#property version "1.00"
#property description "SaherElm X121XKI Signaller Class"
#property strict
//
// Imports ...
#include "../../Classes/x-saherelm.x-signaller.class.mq5"
#include "../../Helpers/x-saherelm.x121.xki.helper.mq5"
#include "../Classes/x-saherelm.x121.xki.parser.class.mq5"
#include "../Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5"
#include "../Classes/x-saherelm.x121.xki.x-poi.drawer.class.mq5"
//
// Implementation ...
//
// Base X121XKI base Signaller ...
class XCX121XKIBaseSignaller : public XCBaseSignaller
{
//
// Public ...
public:
//
// Props ...
//
CArrayObj drawnObjects; // Drawing Objects Holder ...
X121XKIInputs kiInputs; // X121XKI Inputs ...
XCX121XKIHelper *kiHelper; // X121XKI Indicator Helper ...
XCX121XKIPOIDrawer *poiDrawer; // X121XKI POI Drawer ...
XCX121XKIPOIDetector *poiDetector; // X121XKI POI Detector ...
XCX121XKIHelperParser *kiParser; // X121XKI Helper Parser ...
//
// Constructor ...
XCX121XKIBaseSignaller(
string _name, // Name ...
string _symbol, // Symbol ...
ENUM_TIMEFRAMES _period, // Period ...
X121XKIInputs &_kiInputs, // X121XKIInputs ...
bool _processAllTicks = false, // Process All Ticks ...
double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ...
double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ...
double _defaultSignalVolume = 0.01 // Default Signal Volume ...
) : XCBaseSignaller(_name,
_symbol,
_period,
_processAllTicks,
_defaultSignalR2R,
_defaultSignalRiskInPoint,
_defaultSignalVolume //
)
{
//
// Instantiating X121XKI Indicator Helper Class ...
if (_kiInputs.IsValid())
{
//
kiHelper = new XCX121XKIHelper();
bool isInited = kiHelper.Init(
_symbol,
_period,
_kiInputs //
);
if (isInited)
{
kiInputs = _kiInputs;
}
else
{
//
delete kiHelper;
ZeroMemory(kiHelper);
}
}
//
// Instantiate X121XKI Helper Parser ...
kiParser = new XCX121XKIHelperParser(kiHelper);
//
poiDrawer = new XCX121XKIPOIDrawer();
poiDetector = new XCX121XKIPOIDetector(kiHelper, kiParser);
}
//
// Deconstructor ...
~XCX121XKIBaseSignaller()
{
Destroy();
}
//
// Overrides ...
//
// Actions ...
/**
* Destroy ...
*/
void Destroy()
{
//
BeforeDestroy();
//
kiInputs.Clean();
//
delete poiDrawer;
ZeroMemory(poiDrawer);
//
delete poiDetector;
ZeroMemory(poiDetector);
//
delete kiHelper;
ZeroMemory(kiHelper);
}
//
// Virtuals ...
/**
* Before Destroy ...
*/
void virtual BeforeDestroy()
{
}
/**
* Processing Tick ...
*
* @param barIndex: int, Specified Bar Index ...
*/
virtual void ProcessTick(int barIndex = 0)
{
}
/**
* Processing New Bar ...
*
* @param barIndex: int, Specified Bar Index ...
*/
virtual void ProcessNewBar(int barIndex = 0)
{
}
/**
* Check Guards Based on MarketConditions ...
*
* @param guards: XGuard, reference collection to holds result ...
* @param positions: XPosition, reference collection to provides positions ...
* @param barIndex: int
*
* @return ( int )
*/
int virtual CheckForGuard(
XGuard &guards[],
XPosition &positions[],
int barIndex = 0 //
)
{
//
int result = 0;
//
SpecifiedClean(guards);
//
result = ArraySize(guards);
//
return result;
}
/**
* Check Additional Validations on Childs Instances ...
*
* @return ( bool virtual )
*/
bool virtual CheckAdditionslSignallerValidations()
{
//
bool result = false;
//
// Validate Fima Helper Requirements ...
result = kiInputs.IsValid() &&
kiHelper != NULL &&
poiDetector != NULL;
if (!result)
{
return result;
}
//
return result;
}
/**
* Normalizing Signal by Signaller Custom Props ...
*
* @param signal: XSignal ...
*/
void virtual NormalizeSignal(XSignal &signal)
{
}
//
// Protected ...
protected:
//
//
// Protected Actions ...
//
// Private ...
private:
//
};
//
// X121XKI Strategy 1 Signaller Class ...
class XCX121XKIStrategy1Signaller : public XCX121XKIBaseSignaller
{
//
// Public ...
public:
//
// Props ...
//
// Constructor ...
XCX121XKIStrategy1Signaller(
string _symbol, // Symbol ...
ENUM_TIMEFRAMES _period, // Period ...
X121XKIInputs &_kiInputs, // X121XKIInputs ...
bool _processAllTicks = false, // Process All Ticks ...
double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ...
double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ...
double _defaultSignalVolume = 0.01 // Default Signal Volume ...
) : XCX121XKIBaseSignaller("X121XKI1",
_symbol,
_period,
_kiInputs,
_processAllTicks,
_defaultSignalR2R,
_defaultSignalRiskInPoint,
_defaultSignalVolume //
)
{
}
//
// Deconstructor ...
~XCX121XKIStrategy1Signaller()
{
//
Destroy();
}
//
// Overrides ...
/**
* Processing Tick ...
*
* @param barIndex: int, Specified Bar Index ...
*/
virtual void ProcessTick(int barIndex = 0)
{
}
/**
* Processing New Bar ...
*
* @param barIndex: int, Specified Bar Index ...
*/
virtual void ProcessNewBar(int barIndex = 0)
{
//
// Normalize ...
barIndex = NormalizeInt(barIndex, 0);
//
XOHCL iBar;
XBoxZone iZone;
XSignal iSignal;
bool has = false;
XTarget iTargets[];
bool isBullish = false;
bool isBearish = false;
ENUM_X_DIRECTION iDir = X_DIRECTION_NONE;
//
// Initialize Bar as CBar ...
has = iBar.Init(
symbol,
period,
barIndex //
);
if (!has)
{
//
iBar.Clean();
return;
}
//
// Strategy X ...
has = HasSignal(
iBar,
iZone,
iTargets,
iDir //
);
//
// Handle Resting Signals ...
has = HasDirection(iDir) &&
iZone.IsValid();
//
// Prepare Signal ...
if (has)
{
//
isBullish = IsXBullish(iDir);
isBearish = IsXBearish(iDir);
//
// Provided SL ...
double points = GetPoints(symbol);
double spread = GetSpread(symbol);
double entry = GetEntry(symbol, iDir);
//
// Calculate SL Addition ...
double slAddition =
slAdditionDistance <= 0
? 0
: slAdditionDistance * points;
//
// Calculate SL Price ...
double sl =
isBullish
? iZone.lower - slAddition
: iZone.upper + slAddition;
//
// Prepare Signal ...
has = PrepareSignal(
iSignal,
iDir,
iTargets,
0, // Use Default R2R ...
sl, // Provided Price for SL ...
0 // Specified Risk in Point ....
);
}
//
// Notify On Signal Event ...
if (has)
{
NotifySignalEventListeners(iSignal);
}
//
// Cleanup ...
iBar.Clean();
iZone.Clean();
iSignal.Clean();
XClean(iTargets);
}
/**
* Check Guards Based on MarketConditions ...
*
* @param guards: XGuard, reference collection to holds result ...
* @param positions: XPosition, reference collection to provides positions ...
* @param barIndex: int
*
* @return ( int )
*/
int virtual CheckForGuard(
XGuard &guards[],
XPosition &positions[],
int barIndex = 0 //
)
{
//
int result = 0;
//
XClean(guards);
return result;
//
int positionsCount = ArraySize(positions);
if (!IsValidSize(positionsCount))
{
return result;
}
//
// Requirements ...
XGuard iGuard;
bool has = false;
int samePeaks = 0;
int sameVales = 0;
double iValue = 0;
double points10 = 0;
double points50 = 0;
double points100 = 0;
int samePVValidation = 5;
bool isPeakOverLast = false;
bool isValeUnderLast = false;
//
for (int i = 0; i < positionsCount; i++)
{
//
points10 = 10 * positions[i].GetPointsValue();
points50 = 50 * positions[i].GetPointsValue();
points100 = 100 * positions[i].GetPointsValue();
//
// Near to TP Guard ...
has = positions[i].profit > 0;
if (has)
{
}
}
//
result = ArraySize(guards);
//
// Cleanup ...
iGuard.Clean();
//
return result;
}
//
// Protected ...
protected:
//
//
// Private ...
private:
//
// Props ...
//
// Implementing Strategies ...
/**
* Check Bar Has Signal Based on Strategy X ...
*
* @param bar: XOHCL, reference to Bar ...
* @param zone: XBoxZone, reference to holds affected zone ...
* @param targets: XTarget, reference to detected Signal's Targets collections ...
* @param dir: ENUM_X_DIRECTION, detected Signal's direction ...
*
* @return ( bool )
*/
bool HasSignal(
XOHCL &bar,
XBoxZone &zone,
XTarget &targets[],
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
// Configuration Flags ...
//
// Signaller Flags ...
bool useSignaller1 = true;
bool useSignaller2 = false;
bool useSignaller3 = false;
bool useSignaller4 = false;
bool useSignaller5 = false;
//
XBoxZone tmpZone;
string provider = NULL;
ENUM_X_DIRECTION tmpDir;
//
bool signaller1HasSignal = false;
bool signaller2HasSignal = false;
bool signaller3HasSignal = false;
bool signaller4HasSignal = false;
bool signaller5HasSignal = false;
//
// Validator Flags ...
bool validateByOrderFlow = false;
//
// Target Flags ...
bool hasPartialCloseOnTp1 = false;
//
bool doRFOnEntryOnTP1 = false;
//
// Draw Flags ...
bool draw = true;
//
// Signal Checking ...
//
// Signal Detection Flags ...
//
// Signaller 1 ...
if (useSignaller1)
{
//
signaller1HasSignal = Strategy1HasSignal(
bar,
tmpZone,
targets,
tmpDir //
);
//
if (signaller1HasSignal)
{
//
provider += "1";
//
if (!zone.IsValid())
{
//
dir = tmpDir;
zone = tmpZone;
}
}
//
tmpZone.Clean();
tmpDir = X_DIRECTION_NONE;
}
//
// Signaller 2 ...
if (useSignaller2)
{
//
signaller2HasSignal = Strategy2HasSignal(
bar,
tmpZone,
targets,
tmpDir //
);
//
if (signaller2HasSignal)
{
//
provider += "2";
//
if (!zone.IsValid())
{
//
dir = tmpDir;
zone = tmpZone;
}
}
//
tmpZone.Clean();
tmpDir = X_DIRECTION_NONE;
}
//
// Signaller 3 ...
if (useSignaller3)
{
//
signaller3HasSignal = Strategy3HasSignal(
bar,
tmpZone,
targets,
tmpDir //
);
//
if (signaller3HasSignal)
{
//
provider += "3";
//
if (!zone.IsValid())
{
//
dir = tmpDir;
zone = tmpZone;
}
}
//
tmpZone.Clean();
tmpDir = X_DIRECTION_NONE;
}
//
// Signaller 4 ...
if (useSignaller4)
{
//
signaller4HasSignal = Strategy4HasSignal(
bar,
tmpZone,
targets,
tmpDir //
);
//
if (signaller4HasSignal)
{
//
provider += "4";
//
if (!zone.IsValid())
{
//
dir = tmpDir;
zone = tmpZone;
}
}
//
tmpZone.Clean();
tmpDir = X_DIRECTION_NONE;
}
//
// Signaller 5 ...
if (useSignaller5)
{
//
signaller5HasSignal = Strategy5HasSignal(
bar,
tmpZone,
targets,
tmpDir //
);
//
if (signaller5HasSignal)
{
//
provider += "5";
//
if (!zone.IsValid())
{
//
dir = tmpDir;
zone = tmpZone;
}
}
//
tmpZone.Clean();
tmpDir = X_DIRECTION_NONE;
}
//
// Summarize Signallers Result ...
result = signaller1HasSignal ||
signaller2HasSignal ||
signaller3HasSignal ||
signaller4HasSignal ||
signaller5HasSignal;
//
// Signal Validating ...
//
// Targets, Restrictions and Risk Management ...
if (result)
{
//
// Requirements ...
XTarget iTarget;
//
// Checking Direction of Signal ...
bool isBullish = IsXBullish(dir);
bool isBearish = IsXBearish(dir);
//
// Provided SL ...
double points = GetPoints(symbol);
double spread = GetSpread(symbol);
double entry = GetEntry(symbol, dir);
//
// Calculate SL Addition ...
double slAddition =
slAdditionDistance <= 0
? 0
: slAdditionDistance * points;
//
// Calculate SL Price ...
double sl =
isBullish
? zone.lower - slAddition
: zone.upper + slAddition;
//
// Calculate Risk ...
double risk = MathAbs(entry - sl);
//
// Calculate Reward ...
double reward = defaultSignalR2R * risk;
//
// Calculate TP1 ...
double tp1 = isBullish
? entry + risk
: entry - risk;
double tp2 = isBullish
? entry + (2 * risk)
: entry - (2 * risk);
//
// Calculate TP ...
double tp = isBullish
? entry + reward
: entry - reward;
//
// Check Max Allowed Risk ...
bool hasTooMuchRisk = maxAllowedRiskDistance <= 0
? false
: risk >= (maxAllowedRiskDistance * points);
if (hasTooMuchRisk)
{
//
// Clean Signal if Too much Risk ...
zone.Clean();
dir = X_DIRECTION_NONE;
}
//
// Common Targets ...
//
// Partial Close on TP 1 ...
if (hasPartialCloseOnTp1)
{
//
iTarget.Clean();
iTarget.target = tp1;
iTarget.actingDistance = 5;
iTarget.volumeMultiplier = 0.8;
iTarget.doRFOnEntry = doRFOnEntryOnTP1;
//
AddRef(iTarget, targets);
}
//
// Custom Signaller Targets ...
//
// Restrictions Handling ...
if (risk > 0 && HasRestrictions())
{
//
// Reset Restricitons if necessary ...
ResetRestrictions();
//
// Handle Custom Restrictions Senario ...
}
//
// Ignore Targets ...
if (ignoreTargets)
{
XClean(targets);
}
//
// Summarize Result ...
result = zone.IsValid() &&
HasDirection(dir);
//
// Cleanup ...
iTarget.Clean();
}
//
// Draws ...
if (result && draw)
{
//
// Other Drawing Materials ...
XPOIDrawConfig drawConfig;
drawConfig.Default();
//
poiDrawer.DrawZone(zone, drawConfig);
}
//
// Cleanup ...
if (!result)
{
//
zone.Clean();
XClean(targets);
dir = X_DIRECTION_NONE;
}
//
// Cleanup ...
tmpZone.Clean();
//
return result;
}
//
// Custom Signal Strategies ...
/**
* Check Bar Has Signal Based on Strategy 1 ...
*
* Pattern‑based reversal:
* - Detects Pin Bar or Signal Key Bar.
* - Confirms with POI detector.
* - Good for reversals at support/resistance.
*
* @param bar: XOHCL, reference to Bar ...
* @param zone: XBoxZone, reference to holds affected zone ...
* @param targets: XTarget, reference to detected Signal's Targets collections ...
* @param dir: ENUM_X_DIRECTION, detected Signal's direction ...
*
* @return ( bool )
*/
bool Strategy1HasSignal(
XOHCL &bar,
XBoxZone &zone,
XTarget &targets[],
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
zone.Clean();
XClean(targets);
dir = X_DIRECTION_NONE;
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
result = poiDetector.IsKISignal(
dir,
bar.Index() //
);
bool isBullish = result &&
IsXBullish(dir);
bool isBearish = result &&
IsXBearish(dir);
result = isBullish ||
isBearish;
if (!result)
{
return result;
}
//
// Detect Nearest Directional ...
int nearestDirectionalSwitchIndex = -1;
if (isBullish)
{
//
isBullish = poiDetector.NearestKIFastSwitchedToBullish(
nearestDirectionalSwitchIndex,
bar.Index() + 2 //
);
}
else
{
//
isBearish = poiDetector.NearestKIFastSwitchedToBearish(
nearestDirectionalSwitchIndex,
bar.Index() + 2 //
);
}
result =
IsValidIndex(nearestDirectionalSwitchIndex) &&
(isBullish ||
isBearish);
if (!result)
{
//
bar.Clean();
return result;
}
//
// Preparing Zone ...
double upper = bar.FindHighest(nearestDirectionalSwitchIndex - bar.Index(), MODE_HIGH);
double lower = bar.FindLowest(nearestDirectionalSwitchIndex - bar.Index(), MODE_LOW);
//
result = zone.Init(
symbol,
period,
upper,
lower,
GetBarTime(symbol, period, nearestDirectionalSwitchIndex),
bar.time,
dir,
"XKI1" //
);
//
// Support and Resistance ...
XBoxZone support;
XBoxZone resistance;
if (result)
{
//
XOHCL tmpBar;
int tmpIDX = -1;
bool has = false;
double upper = 0;
double lower = 0;
int length = zone.GetAge();
//
// Support ...
tmpIDX = bar.FindLowestIndex(length, MODE_LOW);
if (IsValidIndex(tmpIDX))
{
//
if (tmpBar.Init(symbol, period, tmpIDX))
{
//
lower = iLow(symbol, period, tmpIDX);
upper = bar.FindLowest(length, MODE_CLOSE);
if (upper <= lower)
{
upper = tmpBar.GetDown();
}
//
has = support.Init(
symbol,
period,
upper,
lower,
tmpBar.time,
bar.time,
X_DIRECTION_BULLISH,
X_BAR_PATTERN_SUPPORT //
);
//
tmpBar.Clean();
}
}
//
// Resistance ...
tmpIDX = bar.FindHighestIndex(length, MODE_HIGH);
if (IsValidIndex(tmpIDX))
{
//
if (tmpBar.Init(symbol, period, tmpIDX))
{
//
upper = iHigh(symbol, period, tmpIDX);
lower = bar.FindHighest(length, MODE_CLOSE);
if (upper <= lower)
{
upper = tmpBar.GetUp();
}
//
has = resistance.Init(
symbol,
period,
upper,
lower,
tmpBar.time,
bar.time,
X_DIRECTION_BEARISH,
X_BAR_PATTERN_RESISTANCE //
);
//
tmpBar.Clean();
}
}
}
//
// TODO: Rempve ...
if (result)
{
//
// Other Drawing Materials ...
XPOIDrawConfig drawConfig;
drawConfig.Default();
//
poiDrawer.DrawZone(zone, drawConfig);
//
if (support.IsValid())
{
poiDrawer.DrawZone(support, drawConfig);
}
//
if (resistance.IsValid())
{
poiDrawer.DrawZone(resistance, drawConfig);
}
//
drawConfig.Clean();
//
// DebugBreak();
}
//
result =
result &&
zone.IsValid() &&
HasDirection(dir);
//
return result;
}
/**
* Check Bar Has Signal Based on Strategy 2 ...
*
* Trend‑following:
* - Requires KI Fast + KI Slow alignment.
* - Confirms with MA crossover.
* - RSI filter to avoid false signals.
*
* @return ( bool )
*/
bool Strategy2HasSignal(
XOHCL &bar,
XBoxZone &zone,
XTarget &targets[],
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
zone.Clean();
XClean(targets);
dir = X_DIRECTION_NONE;
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
bool isBullish = kiParser.IsBullishMomentumTrend(bar.Index());
bool isBearish = kiParser.IsBearishMomentumTrend(bar.Index());
result = isBullish ||
isBearish;
if (!result)
{
return result;
}
//
dir = isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
result = ToBox(bar, zone, dir, X_BAR_PATTERN_MOMENTUM);
result =
result &&
zone.IsValid() &&
HasDirection(dir);
//
return result;
}
/**
* Check Bar Has Signal Based on Strategy 3 ...
*
* Breakout:
* - Detects price breaking KI bands with ATR confirmation.
* - Confirms with Momentum Bar pattern.
*
* @return ( bool )
*/
bool Strategy3HasSignal(
XOHCL &bar,
XBoxZone &zone,
XTarget &targets[],
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
zone.Clean();
XClean(targets);
dir = X_DIRECTION_NONE;
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
bool isBullish = poiDetector.IsBullishBreakoutPOI(bar.Index());
bool isBearish = poiDetector.IsBearishBreakoutPOI(bar.Index());
result = isBullish ||
isBearish;
if (!result)
{
return result;
}
//
dir = isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
result = ToBox(bar, zone, dir, X_BAR_PATTERN_TRUE_GAPED);
result =
result &&
zone.IsValid() &&
HasDirection(dir);
//
return result;
}
/**
* Check Bar Has Signal Based on Strategy 4 ...
*
* Exhaustion:
* - Strong trend + RSI extreme + volatility low.
* - Confirms with Piercing/Dark Cloud Cover candlestick.
*
* @return ( bool )
*/
bool Strategy4HasSignal(
XOHCL &bar,
XBoxZone &zone,
XTarget &targets[],
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
zone.Clean();
XClean(targets);
dir = X_DIRECTION_NONE;
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
bool isBullish = poiDetector.IsBullishTrendExhaustedPOI(bar.Index());
bool isBearish = poiDetector.IsBearishTrendExhaustedPOI(bar.Index());
result = isBullish ||
isBearish;
if (!result)
{
return result;
}
//
dir = isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
result = ToBox(bar, zone, dir, X_BAR_PATTERN_PIERCING);
result =
result &&
zone.IsValid() &&
HasDirection(dir);
//
return result;
}
/**
* Check Bar Has Signal Based on Strategy 5 ...
*
* Continuation:
* - Requires strong trend confirmation (KI fast/slow + MA crossover + RSI filter).
* - Confirms with continuation candlestick patterns (Flag or Rising pattern).
* - Ensures zone validity for entry.
*
* @return ( bool )
*/
bool Strategy5HasSignal(
XOHCL &bar,
XBoxZone &zone,
XTarget &targets[],
ENUM_X_DIRECTION &dir //
)
{
//
bool result = false;
//
zone.Clean();
XClean(targets);
dir = X_DIRECTION_NONE;
//
result = bar.IsValid();
if (!result)
{
return result;
}
//
bool isBullish = kiParser.IsTrendStrongBullish(bar.Index());
bool isBearish = kiParser.IsTrendStrongBearish(bar.Index());
result = isBullish ||
isBearish;
if (!result)
{
return result;
}
//
// Confirm Direction by Candlestick Continuation Patterns ...
isBullish =
isBullish &&
poiDetector.IsBullishContinuationPOI(bar.Index());
isBearish =
isBearish &&
poiDetector.IsBearishContinuationPOI(bar.Index());
result = isBullish ||
isBearish;
if (!result)
{
return result;
}
//
dir = isBullish
? X_DIRECTION_BULLISH
: isBearish
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
result = ToBox(bar, zone, dir, X_BAR_PATTERN_PIERCING);
result =
result &&
zone.IsValid() &&
HasDirection(dir);
//
return result;
}
//
};
//