From b1731af03c8c5ff4a24b3c13c9290dbed0f7a9a5 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Tue, 30 Dec 2025 21:38:58 +0330 Subject: [PATCH] last works on xki ... --- .../x-saherelm.x121.xki.signaller.class.mq5 | 1184 ++++++++++++++ Experts/x-saherelm.x121.xki.backtester.ea.mq5 | 871 +++++++++++ Helpers/x-saherelm.x121.xki.helper.mq5 | 229 ++- Indicators/x-saherelm.x121.xki.mq5 | 188 ++- .../x-saherelm.x121.xki.parser.class.mq5 | 1389 +++++++++++++++++ .../x-saherelm.x121.xki.signaller.class.mq5 | 1187 ++++++++++++++ ...saherelm.x121.xki.x-poi.detector.class.mq5 | 973 ++++++++++++ ...x-saherelm.x121.xki.x-poi.drawer.class.mq5 | 707 +++++++++ 8 files changed, 6662 insertions(+), 66 deletions(-) create mode 100644 Documents/BKP/x-saherelm.x121.xki.signaller.class.mq5 create mode 100644 Experts/x-saherelm.x121.xki.backtester.ea.mq5 create mode 100644 X121XKIEA/Classes/x-saherelm.x121.xki.parser.class.mq5 create mode 100644 X121XKIEA/Classes/x-saherelm.x121.xki.signaller.class.mq5 create mode 100644 X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5 create mode 100644 X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.drawer.class.mq5 diff --git a/Documents/BKP/x-saherelm.x121.xki.signaller.class.mq5 b/Documents/BKP/x-saherelm.x121.xki.signaller.class.mq5 new file mode 100644 index 00000000..0d4dcab7 --- /dev/null +++ b/Documents/BKP/x-saherelm.x121.xki.signaller.class.mq5 @@ -0,0 +1,1184 @@ +/////////////////////////////////////////////////////// +// +// 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; + } + + // + bool isBullish = poiDetector.IsBullishPOI(bar.Index()); + bool isBearish = poiDetector.IsBearishPOI(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_SIGNALKEY); + 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; + } + + // +}; + +// \ No newline at end of file diff --git a/Experts/x-saherelm.x121.xki.backtester.ea.mq5 b/Experts/x-saherelm.x121.xki.backtester.ea.mq5 new file mode 100644 index 00000000..317d9b48 --- /dev/null +++ b/Experts/x-saherelm.x121.xki.backtester.ea.mq5 @@ -0,0 +1,871 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ------------------------------------------------- +// Name: X121XKIEABackTester +// Description: Base Expert Advisor as Template ... +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property icon "../Images/SaherElm_Logo_Color.ico" +#property description "SaherElm XFIMA Expert Advisor" +#property strict + +// +#define ShortName "X121XKIEABackTester" + +// +// Importts ... +#include "../Classes/x-saherelm.x-backtester.expert.class.mq5" +#include "../X121XKIEA/Classes/x-saherelm.x121.xki.signaller.class.mq5" + +// #region Inputs ... +// #region Commons ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix +// #endregion + +// #region Volume ... +input group "Volume"; +input ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect = X_VOLUME_CONSTANT; // Volume Applying Type +input double eaStaticVoluem = 0.0; // Static Volume +input double eaDynamicVolumeStepBalance = 0.0; // Step of Balance for Increase Volume +input double eaDynamicVolumeStepVolume = X_MIN_VOLUME; // Step of Volume Increasing +input double eaConstantRiskBalance = 0.0; // Constant Risk Balance per Trade +input double eaConstantPercent = 1; // Constant Percent of Balance Per Trade +input double eaConstantBalance = 1000.0; // Constant Balance for Calculations + // #endregion + +// #region Alert ... +input group "Alert"; +input bool eaEnableAlerts = true; // Enable Alerts +input bool eaLogAlerts = true; // Log Alerts +input bool eaMailAlerts = false; // Mail Alerts +input bool eaPushAlerts = false; // Push Alerts +input bool eaTerminalAlerts = false; // Terminal Alerts +// #endregion + +// #region Configurations ... +input group "Configuration"; +input bool eaProcessAllTicks = false; // Process All Ticks +input double eaSignallerR2R = 2.0; // Risk To Reward Ratio +input double eaSignallerVolume = 0.01; // Default Volume +input double eaSignallerRiskInPoint = 50; // Default Risk In Point + // #endregion + +// #region Bar Time ... +input group "Bar Timer"; +input int barTimeFontSize = 10; // Font Size +input string barTimeFont = "Arial"; // Font +input color barTimeColor = clrYellow; // Text Color +input ENUM_BASE_CORNER barTimeCorner = CORNER_RIGHT_LOWER; // Text Position +input bool showBars = true; // Show Bars +input bool showBarTime = true; // Show Bar Time +// #endregion + +// #region Indicator Inputs ... +// +input group "Calculation"; +input int kiFastLength = 26; // KI Fast Length +input int kiSlowLength = 104; // KI Slow Length +input int maFastLength = 9; // MA Fast Length +input int maSlowLength = 26; // MA Slow Length +input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Mode +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // MA Applied To +input int rsiLength = 14; // RSI Length +input ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To +input int kiWaveSmoothingLength = 14; // RSI KI Wave Smoothing Length +input ENUM_X_MA_METHOD kiWaveSmoothingMode = X_MA_MODE_EMA; // RSI KI Wave Smoothing Method +input double rsiMultiplier = 0.5; // RSI Multiplier +input int atrLength = 14; // ATR Length +input double atrMultiplier = 2; // ATR Multiplier +input int atrSmoothingLength = 14; // ATR Smoothing Length +input ENUM_X_MA_METHOD atrSmoothingMode = X_MA_MODE_EMA; // ATR Smoothing Method +input ENUM_X_PRICE atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Price Type +input ENUM_X_PRICE atrLowerPriceType = X_PRICE_LOW; // ATR Lower Price Type + +// +// Presentation ... +input group "Presentation"; +input bool showKIFast = true; // Show KI Fast +input bool showKISlow = true; // Show KI Slow +input bool showMaFast = true; // Show Ma Fast +input bool showMaSlow = true; // Show MA Slow +input bool showKIWave = true; // Show KI Wave +input bool showKIUpper = true; // Show KI Upper +input bool showKILower = true; // Show KI Lower + +// +input int startCalculationForLastBars = 1500; // Calculate Last n Bars +// #endregion +// #endregion + +// #region Local Variables ... +// +// Requirements ... +string eaLogTag; // EA Log Prefix ... +XCBackTesterEA *eaExpert; // EA Expert ... + +// +// Registered Signallers ... +XCX121XKIStrategy1Signaller *signaller1; // XFIMA1 Signaller ... + +// +XBarTracker eaBarTracker; // EA Bar Traker ... + +// +// Registered Handlers ... +int eaCTHandler = INVALID_HANDLE; // Candle Timer Handler ... +int eaCCHandler = INVALID_HANDLE; // Candle Cleaner Handler ... + +// +bool eaIsNewBar; // Check New Bar ... + +// +ENUM_CHART_MODE eaBarMode = CHART_CANDLES; + +// +color eaBarUpColor = clrLime; +color eaBarDownColor = clrRed; +color eaBarLineColor = clrLime; +color eaBarBearishColor = clrRed; +color eaBarBullishColor = clrLime; +color eaBarVolumesColor = clrGreen; +// #endregion + +// #region Event Handlers ... +// +// Initialization ... +int OnInit() +{ + // + // Preparing Tags ... + string eaTag = + (IsValid(eaLogSuffix) + ? eaLogSuffix + "_" + : "") + + ShortName; + + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Configure EA Expert Class ... + eaExpert = new XCBackTesterEA(); + + // + // Symbol / Period ... + eaExpert.symbol = _Symbol; + eaExpert.period = _Period; + + // + // Common ... + eaExpert.eaMagicNumber = eaMagicNumber; + eaExpert.eaSlippage = eaSlippage; + eaExpert.eaLogSuffix = eaTag; + + // + // Volume ... + eaExpert.eaVolumeSelect = eaVolumeSelect; + eaExpert.eaStaticVoluem = eaStaticVoluem; + eaExpert.eaDynamicVolumeStepBalance = eaDynamicVolumeStepBalance; + eaExpert.eaDynamicVolumeStepVolume = eaDynamicVolumeStepVolume; + eaExpert.eaConstantRiskBalance = eaConstantRiskBalance; + eaExpert.eaConstantPercent = eaConstantPercent; + eaExpert.eaConstantBalance = eaConstantBalance; + + // + // Alert ... + eaExpert.eaEnableAlerts = eaEnableAlerts; + eaExpert.eaLogAlerts = eaLogAlerts; + eaExpert.eaMailAlerts = eaMailAlerts; + eaExpert.eaPushAlerts = eaPushAlerts; + eaExpert.eaTerminalAlerts = eaTerminalAlerts; + + // + // Attach Event Handlers ... + eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged); + eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered); + eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged); + eaExpert.AddOnSignalExecutedEventHandler(OnSignalExecuted); + eaExpert.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaExpert.AddOnModifyPositionEventHandler(OnPositionModified); + eaExpert.AddOnPositionsChangedEventHandler(OnPositionsChanged); + eaExpert.AddOnTradeStateChangedEventHandler(OnTradeStateChanged); + eaExpert.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + eaExpert.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed); + + // + // Configure Other Requirements ... + eaExpert.allowedTPSLStep = 10; + eaExpert.minAllowedRiskInPoint = 20; + eaExpert.volume = eaSignallerVolume; + eaExpert.riskToRewardRatio = eaSignallerR2R; + eaExpert.riskInPoint = eaSignallerRiskInPoint; + + // + // Try to Initialize eaExpert ... + bool isInited = eaExpert.HandleOnInit(); + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + // Here Instantiate Signaller Class ... + + // + // Preparing Indicator Inputs ... + X121XKIInputs kiInputs; + + // + // This is Default Configuration ... + kiInputs.Default(); + kiInputs.Hide(); + + // + // Here we Attach Inputs to Indicator ... + kiInputs.kiFastLength = kiFastLength; + kiInputs.kiSlowLength = kiSlowLength; + kiInputs.maFastLength = maFastLength; + kiInputs.maSlowLength = maSlowLength; + kiInputs.maMethod = maMethod; + kiInputs.maAppliedTo = maAppliedTo; + kiInputs.rsiLength = rsiLength; + kiInputs.rsiAppliedTo = rsiAppliedTo; + kiInputs.kiWaveSmoothingLength = kiWaveSmoothingLength; + kiInputs.kiWaveSmoothingMode = kiWaveSmoothingMode; + kiInputs.rsiMultiplier = rsiMultiplier; + kiInputs.atrLength = atrLength; + kiInputs.atrMultiplier = atrMultiplier; + kiInputs.atrSmoothingLength = atrSmoothingLength; + kiInputs.atrSmoothingMode = atrSmoothingMode; + kiInputs.atrUpperPriceType = atrUpperPriceType; + kiInputs.atrLowerPriceType = atrLowerPriceType; + kiInputs.showKIFast = showKIFast; + kiInputs.showKISlow = showKISlow; + kiInputs.showMaFast = showMaFast; + kiInputs.showMaSlow = showMaSlow; + kiInputs.showKIWave = showKIWave; + kiInputs.showKIUpper = showKIUpper; + kiInputs.showKILower = showKILower; + kiInputs.startCalculationForLastBars = startCalculationForLastBars; + + // + // Instantiate Signaller ... + + // + // X121XKI1 Signaller ... + signaller1 = new XCX121XKIStrategy1Signaller( + _Symbol, + _Period, + kiInputs, + eaProcessAllTicks, // Process All Ticks ... + eaSignallerR2R, // Signaller Risk to Reward Ratio ... + eaSignallerRiskInPoint, // Default Risk In Points ... + eaSignallerVolume // Defaul Volume ... + ); + + // + // Configure Signaller ... + signaller1.ignoreTargets = false; + signaller1.slAdditionDistance = 30; + signaller1.maxAllowedRiskDistance = 350; + signaller1.AddOnSignalEventHandler(OnSignalTriggered); + + // + isInited = + signaller1.IsValid(); + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + // Initialize Candle Timer Handler ... + eaCTHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.x121.xct", + // + // Inputs ... + barTimeFontSize, // Font Size ... + barTimeFont, // Font ... + barTimeColor, // Text Color ... + barTimeCorner, // Text Position ... + // + // Presentation ... + "", + showBarTime // Show Candle Time + // + ); + isInited = eaCTHandler != INVALID_HANDLE; + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + // Initialize Candle Cleaner Handler ... + eaCCHandler = iCustom( + _Symbol, + _Period, + "x-saherelm.x121.xcc", + // + // Inputs ... + // + // Chart Style ... + "", + eaBarMode, // Mode + eaBarUpColor, // Up Color + eaBarDownColor, // Down Color + eaBarLineColor, // Line mode and Doji candlestick Color + eaBarBullishColor, // Bearish Color + eaBarBearishColor, // Bullish Color + eaBarVolumesColor, // Volumes Color + // + // Presentation ... + "", + showBars // Show Candles + // + ); + isInited = eaCCHandler != INVALID_HANDLE; + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + // Initialize Bar Tracker ... + isInited = eaBarTracker.Init( + _Symbol, + _Period // + ); + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + // Configure XFIMA POI Detector / Drawer ... + // detectorConfig.Default(); + // detectorConfig.FullDetect(); + // marketStructureDrawerConfig.FullDraw(); + + // + // Ignoring Position Drawer ... + delete eaExpert.eaPositionDrawer; + ZeroMemory(eaExpert.eaPositionDrawer); + eaExpert.eaPositionDrawer = NULL; + + // + Print(ShortName, ": Initialized Successfully ..."); + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Destroy Timer ... + eaExpert.HandleOnDeInit(); + + // + // De Init Indicator ... + IndicatorRelease(eaCTHandler); + + // + eaBarTracker.Clean(); + + // + delete signaller1; + ZeroMemory(signaller1); + + // + delete eaExpert; + ZeroMemory(eaExpert); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + eaIsNewBar = eaBarTracker.IsNewBar(); + bool canProcess = eaProcessAllTicks + ? true + : eaIsNewBar; + // + eaExpert.HandleOnTick(); + + // + if (!canProcess) + { + return; + } + + // + // Bar Index ... + int barIndex = 0; + + // + // Signallers Calling OnTick ... + signaller1.OnTick(barIndex); + + // + // Checking For Guard only When has Position ... + XPosition positions[]; + int positionsCount = eaExpert.eaTrader.GetPositions( + positions, + signaller1.symbol, + signaller1.name, + signaller1.period, + NULL, // All Types ... + true, // Filter By Magic ... + true // Force Clean ... + ); + if (IsValidSize(positionsCount)) + { + // + XGuard guards[]; + int guardsCount = signaller1.CheckForGuard( + guards, + positions, + barIndex // + ); + if (IsValidSize(guardsCount)) + { + // + // Handling Guards ... + eaExpert.eaGuard.DoGuards(guards); + } + } +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaExpert.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + eaExpert.HandleOnTimer(); +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + eaExpert.HandleOnChartEvent(id, lparam, dparam, sparam); +} +// #endregion + +// #region Custom Event Handlers ... +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 && + // + // Indicator Inputs ... + // + // KI ... + kiFastLength >= 5 && + kiSlowLength > kiFastLength && + // + // ATR ... + atrLength >= 5 && + // + // RSI ... + rsiLength >= 5 + // + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() +{ + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() +{ + // + // TODO: Use This ... + // EventKillTimer(); +} + +/** + * Trigger OnSignal Event ... + * + * @param signal: XSignal + */ +void OnSignalTriggered(XSignal &signal) +{ + // // + // // Draw Signal on Chart ... + // XCSignalObject *iSignalObj; + // bool has = signaller1.poiDrawer.DrawSignal( + // signal, + // iSignalObj, + // 7 // + // ); + + // + eaExpert.HandleOnSignalTriggered(signal); +} + +/** + * Trigger OnSignal Executed Event ... + * + * @param signal: XSignal + */ +void OnSignalExecuted(XSignal &signal) +{ + eaExpert.HandleOnSignalExecuted(signal); +} + +/** + * Check For Guard ... + * + * @param guards: XGuard, reference Collection to holds result ... + * @param positions: XPosition, refrence collection to Provides Positions ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( int ) + */ +int CheckForGuard( + XGuard &guards[], + XPosition &positions[], + int barIndex = 0 // +) +{ + // + int result = signaller1.CheckForGuard( + guards, + positions, + barIndex // + ); + + // + return result; +} + +// +// Trade Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + // + eaExpert.HandleOnStopLossTriggered(deal); + + // + HandleBalanceReport(); + HandleWinTrade(deal.positionId, deal.profit); + HandleLoseTrade(deal.positionId, deal.profit); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + // + eaExpert.HandleOnTakeProfitTriggered(deal); + + // + HandleBalanceReport(); + HandleWinTrade(deal.positionId, deal.profit); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: ULONG ... + * @param position: XPosition instance ... + * @param comment: String ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + eaExpert.HandleOnPositionForceClosed( + ticket, + position, + comment // + ); + + // + HandleBalanceReport(); + HandleWinTrade(ticket, position.profit); + HandleLoseTrade(ticket, position.profit); +} + +/** + * Handle Deals Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnDealsChanged(int count) +{ + eaExpert.HandleOnDealsChanged(count); +} + +/** + * Handle Orders Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnOrdersChanged(int count) +{ + eaExpert.HandleOnOrdersChanged(count); +} + +/** + * Handle Positions Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnPositionsChanged(int count) +{ + eaExpert.HandleOnPositionsChanged(count); +} + +/** + * Handle Position Modified ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionModified( + const ulong ticket, + const double profit, + const string comment // +) +{ + // + eaExpert.HandleOnPositionModified( + ticket, + profit, + comment // + ); +} + +/** + * Handle Position Partial Closed ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // +) +{ + // + eaExpert.HandleOnPositionPartialClosed( + ticket, + profit, + comment // + ); +} + +/** + * Handle Trade State Changed ... + * + * @param state: XOnTradeHandlerState instance ... + */ +void OnTradeStateChanged(const XOnTradeHandlerState &state) +{ + eaExpert.HandleOnTradeStateChanged(state); +} + +/** + * Test Resting Signals ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + */ +void HandleLoseTrade( + ulong ticket = 0, + double profit = 0 // +) +{ + // + // Check Position Loose ... + bool has = ticket > 0 && + profit < 0; + if (!has) + { + return; + } + + // + // NOTE: Here we Can Add Restrictions on Signaller based on our Requirements ... + // restingSignals: Specified Number of Signals which must to Ignore ... + // restUntil: Specified DateTime to Ignore all Signals before it Expiration ... + // restingDelay: Specified Bars Delay to Ignore all Signals before it passed ... + + // + // Increase Resting Signals of Signallers ... + signaller1.LoseTrade(); +} + +/** + * Handle Win Trade ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + */ +void HandleWinTrade( + ulong ticket = 0, + double profit = 0 // +) +{ + // + bool has = ticket > 0 && + profit > 0; + if (!has) + { + return; + } + + // + signaller1.WinTrade(); +} + +/** + * Handle Balance Report ... + */ +void HandleBalanceReport() +{ + // + string message = eaExpert.eaTrader.mAccount.GetBalanceReportMessage(); + eaExpert.eaAlert.SendAlert(message); +} +// #endregion diff --git a/Helpers/x-saherelm.x121.xki.helper.mq5 b/Helpers/x-saherelm.x121.xki.helper.mq5 index bae8a028..6501fcb6 100644 --- a/Helpers/x-saherelm.x121.xki.helper.mq5 +++ b/Helpers/x-saherelm.x121.xki.helper.mq5 @@ -28,16 +28,21 @@ enum ENUM_X121_XKI_BUFFERS { // - // KI ... - X121_XKI_KI_LINE = 0, - X121_XKI_KI_COLOR_LINE = 1, - X121_XKI_KI_STATE_LINE = 8, + // KI Fast ... + X121_XKI_KI_FAST_LINE = 0, + X121_XKI_KI_FAST_COLOR_LINE = 1, + X121_XKI_KI_FAST_STATE_LINE = 10, + // + // KI Slow ... + X121_XKI_KI_SLOW_LINE = 8, + X121_XKI_KI_SLOW_COLOR_LINE = 9, + X121_XKI_KI_SLOW_STATE_LINE = 17, // // KI Wave ... X121_XKI_KI_WAVE_LINE = 2, - X121_XKI_KI_WAVE_RAW_LINE = 13, + X121_XKI_KI_WAVE_RAW_LINE = 15, X121_XKI_KI_WAVE_COLOR_LINE = 3, - X121_XKI_KI_WAVE_STATE_LINE = 14, + X121_XKI_KI_WAVE_STATE_LINE = 16, // // Upper/Lower ... X121_XKI_KI_UPPER_LINE = 4, @@ -48,12 +53,12 @@ enum ENUM_X121_XKI_BUFFERS X121_XKI_MA_SLOW_LINE = 7, // // ATR ... - X121_XKI_ATR_LINE = 9, - X121_XKI_ATR_RAW_UPPER_LINE = 10, - X121_XKI_ATR_RAW_LOWER_LINE = 11, + X121_XKI_ATR_LINE = 11, + X121_XKI_ATR_RAW_UPPER_LINE = 12, + X121_XKI_ATR_RAW_LOWER_LINE = 13, // // RSI ... - X121_XKI_RSI_LINE = 12, + X121_XKI_RSI_LINE = 14, }; // #endregion @@ -62,7 +67,8 @@ struct X121XKIInputs { // #region Props ... // #region Calculations ... - int kiLength; // KI Length + int kiFastLength; // KI Fast Length + int kiSlowLength; // KI Slow Length int maFastLength; // MA Fast Length int maSlowLength; // MA Slow Length ENUM_MA_METHOD maMethod; // MA Mode @@ -81,7 +87,8 @@ struct X121XKIInputs // #endregion // #region Presentations ... - bool showKI; // Show KI + bool showKIFast; // Show KI + bool showKISlow; // Show Slow bool showMaFast; // Show Ma Fast bool showMaSlow; // Show MA Slow bool showKIWave; // Show KI Wave @@ -114,7 +121,8 @@ struct X121XKIInputs { // // Calculations ... - kiLength = 26; + kiFastLength = 26; + kiSlowLength = 104; maFastLength = 9; maSlowLength = 26; maMethod = MODE_EMA; @@ -133,7 +141,8 @@ struct X121XKIInputs // // Presentations ... - showKI = true; + showKIFast = true; + showKISlow = true; showMaFast = true; showMaSlow = true; showKIWave = true; @@ -150,7 +159,8 @@ struct X121XKIInputs { // // Presentations ... - showKI = false; + showKIFast = false; + showKISlow = false; showMaFast = false; showMaSlow = false; showKIWave = false; @@ -169,7 +179,8 @@ struct X121XKIInputs result = // // KI ... - kiLength >= 5 && + kiFastLength >= 5 && + kiSlowLength > kiFastLength && // // ATR ... atrLength >= 5 && @@ -201,15 +212,18 @@ struct X121XKIConditions // #endregion // #region Buffers ... - double kiBuffer[]; - double kiColorBuffer[]; + double kiFastBuffer[]; + double kiFastColorBuffer[]; + double kiFastStateBuffer[]; + double kiSlowBuffer[]; + double kiSlowColorBuffer[]; + double kiSlowStateBuffer[]; double kiWaveBuffer[]; double kiWaveColorBuffer[]; double kiUpperBuffer[]; double kiLowerBuffer[]; double maFastBuffer[]; double maSlowBuffer[]; - double kiStateBuffer[]; double atrBuffer[]; double atrRawUpperBuffer[]; double atrRawLowerBuffer[]; @@ -243,15 +257,18 @@ struct X121XKIConditions // Buffers ... // - XClean(kiBuffer); - XClean(kiColorBuffer); + XClean(kiFastBuffer); + XClean(kiFastColorBuffer); + XClean(kiFastStateBuffer); + XClean(kiSlowBuffer); + XClean(kiSlowColorBuffer); + XClean(kiSlowStateBuffer); XClean(kiWaveBuffer); XClean(kiWaveColorBuffer); XClean(kiUpperBuffer); XClean(kiLowerBuffer); XClean(maFastBuffer); XClean(maSlowBuffer); - XClean(kiStateBuffer); XClean(atrBuffer); XClean(atrRawUpperBuffer); XClean(atrRawLowerBuffer); @@ -260,15 +277,18 @@ struct X121XKIConditions XClean(kiWaveStateBuffer); // - ArraySetAsSeries(kiBuffer, true); - ArraySetAsSeries(kiColorBuffer, true); + ArraySetAsSeries(kiFastBuffer, true); + ArraySetAsSeries(kiFastColorBuffer, true); + ArraySetAsSeries(kiFastStateBuffer, true); + ArraySetAsSeries(kiSlowBuffer, true); + ArraySetAsSeries(kiSlowColorBuffer, true); + ArraySetAsSeries(kiSlowStateBuffer, true); ArraySetAsSeries(kiWaveBuffer, true); ArraySetAsSeries(kiWaveColorBuffer, true); ArraySetAsSeries(kiUpperBuffer, true); ArraySetAsSeries(kiLowerBuffer, true); ArraySetAsSeries(maFastBuffer, true); ArraySetAsSeries(maSlowBuffer, true); - ArraySetAsSeries(kiStateBuffer, true); ArraySetAsSeries(atrBuffer, true); ArraySetAsSeries(atrRawUpperBuffer, true); ArraySetAsSeries(atrRawLowerBuffer, true); @@ -342,7 +362,8 @@ class XCX121XKIHelper : public XCBaseHelper mPeriod, "x-saherelm.x121.xki", "", // Calculation ... - mInputs.kiLength, + mInputs.kiFastLength, + mInputs.kiSlowLength, mInputs.maFastLength, mInputs.maSlowLength, mInputs.maMethod, @@ -359,7 +380,8 @@ class XCX121XKIHelper : public XCBaseHelper mInputs.atrUpperPriceType, mInputs.atrLowerPriceType, "", // Presentation ... - mInputs.showKI, + mInputs.showKIFast, + mInputs.showKISlow, mInputs.showMaFast, mInputs.showMaSlow, mInputs.showKIWave, @@ -450,20 +472,35 @@ class XCX121XKIHelper : public XCBaseHelper int zIndex = barIndex; // #region Reading Buffers ... - CopyKI( + CopyKIFast( zIndex, loopback, - conditions.kiBuffer // + conditions.kiFastBuffer // ); - CopyKIColor( + CopyKIFastColor( zIndex, loopback, - conditions.kiColorBuffer // + conditions.kiFastColorBuffer // ); - CopyKIState( + CopyKIFastState( zIndex, loopback, - conditions.kiStateBuffer // + conditions.kiFastStateBuffer // + ); + CopyKISlow( + zIndex, + loopback, + conditions.kiSlowBuffer // + ); + CopyKISlowColor( + zIndex, + loopback, + conditions.kiSlowColorBuffer // + ); + CopyKISlowState( + zIndex, + loopback, + conditions.kiSlowStateBuffer // ); CopyKIWave( zIndex, @@ -533,21 +570,21 @@ class XCX121XKIHelper : public XCBaseHelper // #endregion // #region Buffer Readers ... - // #region KI ... + // #region KI Fast ... // - double GetKI( + double GetKIFast( int barIndex // Bar Index ) { // return ReadValue( - (int)X121_XKI_KI_LINE, + (int)X121_XKI_KI_FAST_LINE, barIndex // ); } // - int CopyKI( + int CopyKIFast( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -557,7 +594,7 @@ class XCX121XKIHelper : public XCBaseHelper // return ReadValues( buffer, - (int)X121_XKI_KI_LINE, + (int)X121_XKI_KI_FAST_LINE, start, count, asSeries // @@ -565,21 +602,21 @@ class XCX121XKIHelper : public XCBaseHelper } // #endregion - // #region KI Color ... + // #region KI Fast Color ... // - double GetKIColor( + double GetKIFastColor( int barIndex // Bar Index ) { // return ReadValue( - (int)X121_XKI_KI_COLOR_LINE, + (int)X121_XKI_KI_FAST_COLOR_LINE, barIndex // ); } // - int CopyKIColor( + int CopyKIFastColor( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -589,7 +626,7 @@ class XCX121XKIHelper : public XCBaseHelper // return ReadValues( buffer, - (int)X121_XKI_KI_COLOR_LINE, + (int)X121_XKI_KI_FAST_COLOR_LINE, start, count, asSeries // @@ -597,21 +634,21 @@ class XCX121XKIHelper : public XCBaseHelper } // #endregion - // #region KI State ... + // #region KI Fast State ... // - double GetKIState( + double GetKIFastState( int barIndex // Bar Index ) { // return ReadValue( - (int)X121_XKI_KI_STATE_LINE, + (int)X121_XKI_KI_FAST_STATE_LINE, barIndex // ); } // - int CopyKIState( + int CopyKIFastState( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -621,7 +658,103 @@ class XCX121XKIHelper : public XCBaseHelper // return ReadValues( buffer, - (int)X121_XKI_KI_STATE_LINE, + (int)X121_XKI_KI_FAST_STATE_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Slow ... + // + double GetKISlow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_SLOW_LINE, + barIndex // + ); + } + + // + int CopyKISlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_SLOW_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Slow Color ... + // + double GetKISlowColor( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_SLOW_COLOR_LINE, + barIndex // + ); + } + + // + int CopyKISlowColor( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_SLOW_COLOR_LINE, + start, + count, + asSeries // + ); + } + // #endregion + + // #region KI Slow State ... + // + double GetKISlowState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)X121_XKI_KI_SLOW_STATE_LINE, + barIndex // + ); + } + + // + int CopyKISlowState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)X121_XKI_KI_SLOW_STATE_LINE, start, count, asSeries // diff --git a/Indicators/x-saherelm.x121.xki.mq5 b/Indicators/x-saherelm.x121.xki.mq5 index 7c6c4ad0..d08a8880 100644 --- a/Indicators/x-saherelm.x121.xki.mq5 +++ b/Indicators/x-saherelm.x121.xki.mq5 @@ -33,7 +33,8 @@ // #region Inputs ... // input group "Calculation"; -input int kiLength = 26; // KI Length +input int kiFastLength = 26; // KI Fast Length +input int kiSlowLength = 104; // KI Slow Length input int maFastLength = 9; // MA Fast Length input int maSlowLength = 26; // MA Slow Length input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Mode @@ -53,7 +54,8 @@ input ENUM_X_PRICE atrLowerPriceType = X_PRICE_LOW; // ATR Lower Price T // // Presentation ... input group "Presentation"; -input bool showKI = true; // Show KI +input bool showKIFast = true; // Show KI Fast +input bool showKISlow = true; // Show KI Slow input bool showMaFast = true; // Show Ma Fast input bool showMaSlow = true; // Show MA Slow input bool showKIWave = true; // Show KI Wave @@ -85,8 +87,8 @@ input int startCalculationForLastBars = 1500; // Calculate Last n Bars #property indicator_chart_window // -#property indicator_buffers 15 -#property indicator_plots 6 +#property indicator_buffers 18 +#property indicator_plots 7 // #region Plot Buffers ... // #region KI ... @@ -100,7 +102,7 @@ double kiBuffer[]; double kiColorBuffer[]; // -#property indicator_label1 "KI" +#property indicator_label1 "KI Fast" #property indicator_type1 DRAW_COLOR_LINE #property indicator_color1 CLR_NONE, clrGreen, clrRed, clrGray #property indicator_style1 STYLE_SOLID @@ -110,7 +112,7 @@ double kiColorBuffer[]; // #region KI Wave ... // #define kiWaveBufferIndex 2 -#define kiWaveBufferPlotIndex 2 +#define kiWaveBufferPlotIndex 1 double kiWaveBuffer[]; // @@ -128,7 +130,7 @@ double kiWaveColorBuffer[]; // #region KI Upper ... // #define kiUpperBufferIndex 4 -#define kiUpperBufferPlotIndex 4 +#define kiUpperBufferPlotIndex 2 double kiUpperBuffer[]; // @@ -142,7 +144,7 @@ double kiUpperBuffer[]; // #region KI Lower ... // #define kiLowerBufferIndex 5 -#define kiLowerBufferPlotIndex 5 +#define kiLowerBufferPlotIndex 3 double kiLowerBuffer[]; // @@ -156,7 +158,7 @@ double kiLowerBuffer[]; // #region MA Fast ... // #define maFastBufferIndex 6 -#define maFastBufferPlotIndex 6 +#define maFastBufferPlotIndex 4 double maFastBuffer[]; // @@ -170,7 +172,7 @@ double maFastBuffer[]; // #region MA Slow ... // #define maSlowBufferIndex 7 -#define maSlowBufferPlotIndex 7 +#define maSlowBufferPlotIndex 5 double maSlowBuffer[]; // @@ -180,10 +182,28 @@ double maSlowBuffer[]; #property indicator_style6 STYLE_DOT #property indicator_width6 1 // #endregion + +// #region KI Slow ... +// +#define kiSlowBufferIndex 8 +#define kiSlowBufferPlotIndex 6 +double kiSlowBuffer[]; + +// +#define kiSlowColorBufferIndex 9 +double kiSlowColorBuffer[]; + +// +#property indicator_label7 "KI Slow" +#property indicator_type7 DRAW_COLOR_LINE +#property indicator_color7 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style7 STYLE_SOLID +#property indicator_width7 2 +// #endregion // #endregion // -#define mLastBufferIndex 7 +#define mLastBufferIndex 9 // #region Data Buffers ... // @@ -213,6 +233,10 @@ double kiWaveRawBuffer[]; // #define kiWaveStateBufferIndex mLastBufferIndex + 7 double kiWaveStateBuffer[]; + +// +#define kiSlowStateBufferIndex mLastBufferIndex + 8 +double kiSlowStateBuffer[]; // #endregion // #endregion @@ -497,7 +521,8 @@ bool ValidateInputs() result = // // KI ... - kiLength >= 5 && + kiFastLength >= 5 && + kiSlowLength > kiFastLength && // // ATR ... atrLength >= 5 && @@ -522,7 +547,8 @@ int ExtractMaxLengthOfInputs() int result = 0; // - result = MathMax(kiLength, atrLength); + result = MathMax(kiFastLength, atrLength); + result = MathMax(result, kiSlowLength); result = MathMax(result, rsiLength); // @@ -550,7 +576,7 @@ void DefineBuffers() SetIndexBuffer(kiBufferIndex, kiBuffer, INDICATOR_DATA); // - PlotIndexSetInteger(kiBufferPlotIndex, PLOT_SHOW_DATA, showKI); + PlotIndexSetInteger(kiBufferPlotIndex, PLOT_SHOW_DATA, showKIFast); PlotIndexSetDouble(kiBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); // @@ -562,6 +588,24 @@ void DefineBuffers() SetIndexBuffer(kiStateBufferIndex, kiStateBuffer, INDICATOR_CALCULATIONS); // #endregion + // #region KI Slow ... + // + ArraySetAsSeries(kiSlowBuffer, true); + SetIndexBuffer(kiSlowBufferIndex, kiSlowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(kiSlowBufferPlotIndex, PLOT_SHOW_DATA, showKISlow); + PlotIndexSetDouble(kiSlowBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(kiSlowColorBuffer, true); + SetIndexBuffer(kiSlowColorBufferIndex, kiSlowColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(kiSlowStateBuffer, true); + SetIndexBuffer(kiSlowStateBufferIndex, kiSlowStateBuffer, INDICATOR_CALCULATIONS); + // #endregion + // #region KI Upper ... // ENUM_DRAW_TYPE kiUpperDrawType = showKIUpper ? DRAW_LINE : DRAW_NONE; @@ -865,6 +909,19 @@ void CalculateValues( ); // #endregion + // #region KI Slow ... + CalculateKISlow( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + // #endregion + // #region ATR (Ki Upper/Lower) ... CalculateATR( barIndex, @@ -943,8 +1000,8 @@ void CalculateKI( if (isInited) { // - double iLLKI = iBar.FindLowest(kiLength, MODE_LOW); - double iHHKI = iBar.FindHighest(kiLength, MODE_HIGH); + double iLLKI = iBar.FindLowest(kiFastLength, MODE_LOW); + double iHHKI = iBar.FindHighest(kiFastLength, MODE_HIGH); // iKI = (iHHKI + iLLKI) / 2; @@ -967,7 +1024,7 @@ void CalculateKI( // iKIState = bullishState; iKIColor = - !showKI + !showKIFast ? hideColorIDX : bullishColorIDX; } @@ -976,7 +1033,7 @@ void CalculateKI( // iKIState = bearishState; iKIColor = - !showKI + !showKIFast ? hideColorIDX : bearishColorIDX; } @@ -987,6 +1044,101 @@ void CalculateKI( iBar.Clean(); } +/** + * Calculate KI Slow Bufer ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateKISlow( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + barIndex // + ); + + // + double iClose = close[barIndex]; + + // + // Calculate KI / Color ... + double lastKI = + isFirstBar + ? emptyValue + : kiSlowBuffer[lastBarIndex]; + double iKI = lastKI; + if (isInited) + { + // + double iLLKI = iBar.FindLowest(kiSlowLength, MODE_LOW); + double iHHKI = iBar.FindHighest(kiSlowLength, MODE_HIGH); + + // + iKI = (iHHKI + iLLKI) / 2; + if (iLLKI == 0 || iHHKI == 0) + { + iKI = lastKI; + } + } + else + { + iKI = lastKI; + } + kiSlowBuffer[barIndex] = iKI; + + // + double iKIState = neuturalState; + double iKIColor = neuturalColorIDX; + if (iClose > iKI) + { + // + iKIState = bullishState; + iKIColor = + !showKISlow + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iKI) + { + // + iKIState = bearishState; + iKIColor = + !showKISlow + ? hideColorIDX + : bearishColorIDX; + } + kiSlowStateBuffer[barIndex] = iKIState; + kiSlowColorBuffer[barIndex] = iKIColor; + + // + iBar.Clean(); +} + /** * Calculate ATR and Ki Upper/Lower Buffers ... * diff --git a/X121XKIEA/Classes/x-saherelm.x121.xki.parser.class.mq5 b/X121XKIEA/Classes/x-saherelm.x121.xki.parser.class.mq5 new file mode 100644 index 00000000..e6e81cb1 --- /dev/null +++ b/X121XKIEA/Classes/x-saherelm.x121.xki.parser.class.mq5 @@ -0,0 +1,1389 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Parser Class Library +// ---------------------------------------------------- +// Name: XCX121XKIHelperParser +// Description: provides all Indicator +// Helper Parse requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Helpers/x-saherelm.x121.xki.helper.mq5" + +// +// Definitions ... + +// +// Implementation ... + +class XCX121XKIHelperParser : XCBase +{ + // + // Public ... + public: + // + string symbol; + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XCX121XKIHelperParser(XCX121XKIHelper *_helper) + { + // + helper = _helper; + symbol = _helper.GetSymbol(); + period = _helper.GetPeriod(); + } + + // + // Deconstructor ... + ~XCX121XKIHelperParser() + { + ZeroMemory(helper); + } + + // + // Tools ... + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = helper != NULL && + helper.IsValid() && + IsXValid(symbol) && + IsXValid(period); + + // + return result; + } + + /** + * Normalize Bar Index ... + * + * @param barIndex: int, Provided Bar Index ... + * + * @return ( int ) + */ + int NormalizeBarIndex(int barIndex = 0) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + result = helper.NormalizeBarIndex(barIndex); + + // + return result; + } + + // + // Parsers ... + // Indicators Base Conditions ... + + // #region KI Fast ... + bool IsKIFastBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetKIFastState(barIndex); + result = state >= 1; + + // + return result; + } + + bool IsKIFastBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetKIFastState(barIndex); + result = state <= -1; + + // + return result; + } + + bool IsKIFastSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKIFastBullish(barIndex) && + !IsKIFastBullish(barIndex + 1); + + // + return result; + } + + bool IsKIFastSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKIFastBearish(barIndex) && + !IsKIFastBearish(barIndex + 1); + + // + return result; + } + + bool IsKIFastOverLast( + int barIndex = 0, + double distancePoint = 5 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double value = helper.GetKIFast(barIndex); + double pValue = helper.GetKIFast(barIndex + 1); + double point = GetPoints(symbol); + double distance = point * distancePoint; + + // + result = value >= pValue + distance; + + // + return result; + } + + bool IsKIFastUnderLast( + int barIndex = 0, + double distancePoint = 5 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double value = helper.GetKIFast(barIndex); + double pValue = helper.GetKIFast(barIndex + 1); + double point = GetPoints(symbol); + double distance = point * distancePoint; + + // + result = value <= pValue - distance; + + // + return result; + } + + // #endregion + + // #region KI Slow ... + bool IsKISlowBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetKISlowState(barIndex); + result = state >= 1; + + // + return result; + } + + bool IsKISlowBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetKISlowState(barIndex); + result = state <= -1; + + // + return result; + } + + bool IsKISlowSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKISlowBullish(barIndex) && + !IsKISlowBullish(barIndex + 1); + + // + return result; + } + + bool IsKISlowSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKISlowBearish(barIndex) && + !IsKISlowBearish(barIndex + 1); + + // + return result; + } + + bool IsKISlowOverLast( + int barIndex = 0, + double distancePoint = 5 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double value = helper.GetKISlow(barIndex); + double pValue = helper.GetKISlow(barIndex + 1); + double point = GetPoints(symbol); + double distance = point * distancePoint; + + // + result = value >= pValue + distance; + + // + return result; + } + + bool IsKISlowUnderLast( + int barIndex = 0, + double distancePoint = 5 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double value = helper.GetKISlow(barIndex); + double pValue = helper.GetKISlow(barIndex + 1); + double point = GetPoints(symbol); + double distance = point * distancePoint; + + // + result = value <= pValue - distance; + + // + return result; + } + // #endregion + + // #region KI Wave ... + bool IsKIWaveBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetKIWaveState(barIndex) >= 1; + + // + return result; + } + + bool IsKIWaveBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetKIWaveState(barIndex) <= -1; + + // + return result; + } + + bool IsKIWaveSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKIWaveBullish(barIndex) && + !IsKIWaveBullish(barIndex + 1); + + // + return result; + } + + bool IsKIWaveSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKIWaveBearish(barIndex) && + !IsKIWaveBearish(barIndex + 1); + + // + return result; + } + // #endregion + + // #region KI Band ... + bool IsPriceAboveKIUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(priceType); + result = price > helper.GetKIUpper(barIndex); + bar.Clean(); + + // + return result; + } + + bool IsPriceBelowKILower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(priceType); + result = price < helper.GetKILower(barIndex); + bar.Clean(); + + // + return result; + } + + bool IsPriceInsideKIBands( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(priceType); + result = price < helper.GetKIUpper(barIndex) && + price > helper.GetKILower(barIndex); + bar.Clean(); + + // + return result; + } + // #endregion + + // #region MA Fast/Slow ... + bool IsMACrossoverBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetMAFast(barIndex) > helper.GetMASlow(barIndex); + return result; + } + + bool IsMACrossoverBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetMAFast(barIndex) < helper.GetMASlow(barIndex); + return result; + } + + bool IsMACrossoverSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsMACrossoverBullish(barIndex) && + !IsMACrossoverBullish(barIndex + 1); + return result; + } + + bool IsMACrossoverSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsMACrossoverBearish(barIndex) && + !IsMACrossoverBearish(barIndex + 1); + return result; + } + + bool IsMAFastAboveKI(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetMAFast(barIndex) > helper.GetKIFast(barIndex); + return result; + } + + bool IsMASlowAboveKI(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetMASlow(barIndex) > helper.GetKISlow(barIndex); + return result; + } + // #endregion + + // #region ATR ... + bool IsATRBreakoutUp( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(priceType); + result = price > helper.GetATRRawUpper(barIndex); + bar.Clean(); + + // + return result; + } + + bool IsATRBreakoutDown( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(priceType); + result = price < helper.GetATRRawLower(barIndex); + bar.Clean(); + + // + return result; + } + + bool IsVolatilityHigh( + int barIndex = 0, + double threshold = 20 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetATR(barIndex) > threshold; + return result; + } + + bool IsVolatilityLow( + int barIndex = 0, + double threshold = 20 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetATR(barIndex) < threshold; + return result; + } + // #endregion + + // #region RSI ... + bool IsRSIBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetRSI(barIndex) > 50; + return result; + } + + bool IsRSIBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetRSI(barIndex) < 50; + return result; + } + + bool IsRSIOverbought(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetRSI(barIndex) > 70; + return result; + } + + bool IsRSIOversold(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = helper.GetRSI(barIndex) < 30; + return result; + } + + bool IsRSISwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsRSIBullish(barIndex) && !IsRSIBullish(barIndex + 1); + return result; + } + + bool IsRSISwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsRSIBearish(barIndex) && !IsRSIBearish(barIndex + 1); + 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, 20); + + // + 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, 20); + return result; + } + + bool IsBullishReversal(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKIWaveSwitchedToBullish(barIndex) && IsRSIOversold(barIndex); + return result; + } + + bool IsBearishReversal(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsKIWaveSwitchedToBearish(barIndex) && IsRSIOverbought(barIndex); + 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, 20); + + // + 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, 20); + + // + return result; + } + // #endregion + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + XCX121XKIHelper *helper; + + // +}; + +// diff --git a/X121XKIEA/Classes/x-saherelm.x121.xki.signaller.class.mq5 b/X121XKIEA/Classes/x-saherelm.x121.xki.signaller.class.mq5 new file mode 100644 index 00000000..3089ca8b --- /dev/null +++ b/X121XKIEA/Classes/x-saherelm.x121.xki.signaller.class.mq5 @@ -0,0 +1,1187 @@ +/////////////////////////////////////////////////////// +// +// 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; + } + + // + DebugBreak(); + + // + result = ToBox(bar, zone, dir, X_BAR_PATTERN_SIGNALKEY); + 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; + } + + // +}; + +// \ No newline at end of file diff --git a/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5 b/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5 new file mode 100644 index 00000000..819cd9e6 --- /dev/null +++ b/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.detector.class.mq5 @@ -0,0 +1,973 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCX121XKIPoiDetector ... +// Description: X121XKI POI Detector Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121XKI POI Detector Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-market.pattern.class.mq5" +#include "../../Helpers/x-saherelm.x121.xki.helper.mq5" +#include "../Classes/x-saherelm.x121.xki.parser.class.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCX121XKIPOIDetector : public XCMarketPatternDetector +{ + // + // Public ... + public: + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + XCBarAnalyser *barAnalyser; // Bar Analyser ... + XCX121XKIHelper *kiHelper; // X121XKI Helper ... + XCX121XKIHelperParser *kiParser; // X121XKI Helper Parser ... + + // + // Constructor ... + XCX121XKIPOIDetector( + XCX121XKIHelper *_kiHelper, + XCX121XKIHelperParser *_kiParser // + ) : XCMarketPatternDetector() + { + // + barAnalyser = new XCBarAnalyser(); + kiHelper = _kiHelper; + kiParser = _kiParser; + + // + symbol = kiHelper.GetSymbol(); + period = kiHelper.GetPeriod(); + } + + // + // Deconstructor ... + ~XCX121XKIPOIDetector() + { + Destroy(); + } + + // + // Actions and Tools ... + + // #region POI Detectors ... + bool NearestKIFastBullish( + int &index, + int barIndex = 0, + int loopback = 50 // + ) + { + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKIFastBullish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + bool NearestKIFastBearish( + int &index, + int barIndex = 0, + int loopback = 50 // + ) + { + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKIFastBearish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + bool NearestKIFastSwitchedToBullish( + int &index, + int barIndex = 0, + int loopback = 50 // + ) + { + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKIFastSwitchedToBullish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + bool NearestKIFastSwitchedToBearish( + int &index, + int barIndex = 0, + int loopback = 50 // + ) + { + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKIFastSwitchedToBearish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + bool NearestKISlowBullish( + int &index, + int barIndex = 0, + int loopback = 50 // + ) + { + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKISlowBullish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + bool NearestKISlowBearish( + int &index, + int barIndex = 0, + int loopback = 50 // + ) + { + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKISlowBearish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + bool NearestKISlowSwitchedToBullish( + int &index, + int barIndex = 0, + int loopback = 50 // + ) + { + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKISlowSwitchedToBullish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + bool NearestKISlowSwitchedToBearish( + int &index, + int barIndex = 0, + int loopback = 50 // + ) + { + // + bool result = false; + + // + index = -1; + + // + // Normalize ... + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + // Loop Back ... + bool isPassed = false; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + isPassed = kiParser.IsKISlowSwitchedToBearish(i); + if (isPassed) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + // #endregion + + // #region Detectors ... + bool 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; + ENUM_X_DIRECTION dir; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + IsPinnedBar(bar, dir) && + IsXBullish(dir); + + // + 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; + ENUM_X_DIRECTION dir; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + IsPinnedBar(bar, dir) && + IsXBearish(dir); + + // + bar.Clean(); + + // + 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; + ENUM_X_DIRECTION dir; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + IsMomentumBar(bar, dir) && + IsXBullish(dir); + + // + 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; + ENUM_X_DIRECTION dir; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + IsMomentumBar(bar, dir) && + IsXBearish(dir); + + // + bar.Clean(); + + // + 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; + ENUM_X_DIRECTION dir; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + IsStarPattern(bar, dir) && + IsXBullish(dir); + + // + 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; + ENUM_X_DIRECTION dir; + result = result && + bar.Init(symbol, period, barIndex); + if (!result) + { + return result; + } + + // + result = result && + IsStarPattern(bar, dir) && + IsXBearish(dir); + + // + bar.Clean(); + + // + 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 IsBullishExhaustionPOI(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + result = kiParser.IsTrendStrongBullish(barIndex) && + kiParser.IsRSIOverbought(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; + } + + // + result = result && + IsPiercingPattern(bar, dir) && + IsXBullish(dir); + + // + bar.Clean(); + + // + return result; + } + + bool IsBearishExhaustionPOI(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + result = kiParser.IsTrendStrongBearish(barIndex) && + kiParser.IsRSIOversold(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; + } + + // + result = result && + IsPiercingPattern(bar, dir) && + IsXBearish(dir); + + // + bar.Clean(); + + // + return result; + } + + bool IsBullishTrendExhaustedPOI(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + result = kiParser.IsTrendStrongBullish(barIndex) && + kiParser.IsVolatilityLow(barIndex, 20) && + kiParser.IsRSIOverbought(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; + } + + // + result = result && + IsPiercingPattern(bar, dir) && + IsXBullish(dir); + + // + bar.Clean(); + + // + return result; + } + + bool IsBearishTrendExhaustedPOI(int barIndex = 0) + { + // + bool result = false; + + // + barIndex = kiParser.NormalizeBarIndex(barIndex); + + // + result = kiParser.IsTrendStrongBearish(barIndex) && + kiParser.IsVolatilityLow(barIndex, 20) && + kiParser.IsRSIOversold(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; + } + + // + result = result && + IsPiercingPattern(bar, dir) && + IsXBearish(dir); + + // + bar.Clean(); + + // + return result; + } + // #endregion + + // #region XDetectors ... + 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 + + // + // Others ... + + /** + * Destroy ... + */ + void Destroy() + { + // + delete barAnalyser; + ZeroMemory(barAnalyser); + + // + ZeroMemory(kiHelper); + ZeroMemory(kiParser); + } + + // + // Testers ... + + // + // Protected ... + protected: + // + // Props ... + + // + // Private ... + private: + // + + // +}; + +// \ No newline at end of file diff --git a/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.drawer.class.mq5 b/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.drawer.class.mq5 new file mode 100644 index 00000000..6bde21b0 --- /dev/null +++ b/X121XKIEA/Classes/x-saherelm.x121.xki.x-poi.drawer.class.mq5 @@ -0,0 +1,707 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCX121XKIPoiDrawer ... +// Description: X121XKI POI Drawer Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121XKI POI Drawer Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" + +// +// Implementation ... +class XCX121XKIPOIDrawer : public XCPOIDrawer +{ + // + public: + // + // Props ... + + // + // Tested Zones ... + color testedBullishColor; + color testedBearishColor; + + // + // Breaked Zones ... + color breakedBullishColor; + color breakedBearishColor; + + // + // FakeBreaked Zones ... + color fakeBreakedBullishColor; + color fakeBreakedBearishColor; + + // + // Constructor ... + XCX121XKIPOIDrawer() : XCPOIDrawer() + { + Default(); + } + + // + // Deconstructor ... + ~XCX121XKIPOIDrawer() + { + } + + // + // Overrides ... + + /** + * Do additional Configurations for Child Classes ... + */ + void virtual Default() override + { + // + // Apply Default Props ... + + // + Prefix(NULL); + ChartIdentification(0); + SubWindowIdentification(0); + + // + defaultBullishStyle.width = 1; + defaultBullishStyle.clr = clrAqua; + defaultBullishStyle.style = STYLE_SOLID; + + // + defaultBearishStyle.width = 1; + defaultBearishStyle.clr = clrMagenta; + defaultBearishStyle.style = STYLE_SOLID; + + // + boxBullishStyle = defaultBullishStyle; + boxBearishStyle = defaultBearishStyle; + + // + testedBullishColor = clrLime; + breakedBullishColor = clrGreen; + fakeBreakedBullishColor = clrYellow; + + // + testedBearishColor = clrRed; + breakedBearishColor = clrDarkRed; + fakeBreakedBearishColor = clrDarkOrange; + } + + // + // Get Specified Directional Arrow Anchor ... + ENUM_ARROW_ANCHOR GetArrowAnchor(ENUM_X_DIRECTION forDir) + { + // + ENUM_ARROW_ANCHOR result = ANCHOR_BOTTOM; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? ANCHOR_TOP + : ANCHOR_BOTTOM; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Code ... + int GetArrowCode(ENUM_X_DIRECTION forDir) + { + // + int result = 159; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? 233 + : 234; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Code ... + color GetArrowColor(ENUM_X_DIRECTION forDir) + { + // + color result = clrYellow; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? clrAqua + : clrMagenta; + } + + // + return result; + } + + // + // Get Specified Directional Arrow Price Type ... + ENUM_X_PRICE GetArrowPriceType(ENUM_X_DIRECTION forDir) + { + // + ENUM_X_PRICE result = X_PRICE_CLOSE; + + // + if (HasDirection(forDir)) + { + // + result = + IsSpecifiedBullish(forDir) + ? X_PRICE_LOW + : X_PRICE_HIGH; + } + + // + return result; + } + + /** + * Get Tested Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetTestedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? testedBullishColor + : testedBearishColor; + + // + return result; + } + + /** + * Get Patterns Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetPatternStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetPatternStyle( + style, + zone.dir // + ); + + // + return result; + } + + /** + * Get Patterns Zone Style ... + * + * @param style: reference to hold result ... + * @param forDir: Specified Direction ... + * + * @return ( bool ) + */ + bool GetPatternStyle( + XPOIStyle &style, + ENUM_X_DIRECTION forDir // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + forDir // + ); + + // + style.width = 2; + style.style = STYLE_DASH; + + // + return result; + } + + /** + * Get Breaked Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetBreakedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? breakedBullishColor + : breakedBearishColor; + + // + return result; + } + + /** + * Get Fake Breaked Zone Style ... + * + * @param style: reference to hold result ... + * @param zone: Specified Zone ... + * + * @return ( bool ) + */ + bool GetFakeBreakedStyle( + XPOIStyle &style, + XBoxZone &zone // + ) + { + // + bool result = false; + + // + style.Clean(); + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + GetBoxStyle( + style, + zone.dir // + ); + + // + style.width = 3; + style.clr = + zone.IsBullish() + ? fakeBreakedBullishColor + : fakeBreakedBearishColor; + + // + return result; + } + + /** + * Fill Arrow Based Drawing Specs ... + * + * @param forDir: Specified Direction ... + * @param arrowPriceType: ENUM_X_PRICE, refrence for Arrow Price ... + * @param arrowCode: int, reference for Arrow Code ... + * @param arrowWidth: int, reference for Arrow Width ... + * @param arrowColor: color, reference for Arrow Color ... + * @param arrowAnchor: ENUM_ARROW_ANCHOR, reference for Arrow Anchor ... + */ + void FillArrowSpecs( + ENUM_X_DIRECTION forDir, + ENUM_X_PRICE &arrowPriceType, + int &arrowCode, + int &arrowWidth, + color &arrowColor, + ENUM_ARROW_ANCHOR &arrowAnchor // + ) + { + // + // Prepare ... + arrowCode = 159; + arrowWidth = 2; + arrowColor = CLR_NONE; + arrowAnchor = ANCHOR_BOTTOM; + arrowPriceType = X_PRICE_CLOSE; + + // + if (HasDirection(forDir)) + { + // + arrowCode = GetArrowCode(forDir); + arrowColor = GetArrowColor(forDir); + arrowAnchor = GetArrowAnchor(forDir); + arrowPriceType = GetArrowPriceType(forDir); + } + } + + /** + * Apply Tested Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyTestedStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetTestedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Breaked Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyBreakedStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetBreakedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Tested Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyFakeBreakStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetFakeBreakedStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Pattern Style ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyPatternStyle( + XCBoxObject *&object, + XBoxZone &zone // + ) + { + // + if (!zone.IsValid() || + object == NULL) + { + return; + } + + // + XPOIStyle style; + if (!GetPatternStyle(style, zone)) + { + return; + } + + // + ApplyBoxStyle( + object, + style // + ); + } + + /** + * Apply Patterns Style ... + * + * @param object: reference pointer to Object ... + */ + void ApplyPatternsStyle( + CArrayObj *&objects // + ) + { + // + if (objects == NULL || + objects.Total() == 0) + { + return; + } + + // + bool has = false; + XPOIStyle iStyle; + string iName = NULL; + XCBoxObject *iBoxObj = NULL; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + for (int i = 0; i < objects.Total(); i++) + { + // + iBoxObj = (XCBoxObject *)objects.At(i); + iName = iBoxObj.ObjName(); + + // + iDir = + IsSpecifiedValid(iName) && + Contains( + "BULL", + iName // + ) + ? X_DIRECTION_BULLISH + : IsSpecifiedValid(iName) && + Contains( + "BEAR", + iName // + ) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + has = GetPatternStyle(iStyle, iDir); + if (has) + { + // + ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + /** + * Apply Style to Specified Pivot Object ... + * + * @param object: reference pointer to Object ... + * @param zone: reference to Zone ... + */ + void ApplyPivotStyle( + XCBarArrowObject *&object, + XPOIStyle &style // + ) + { + // + if (object == NULL) + { + return; + } + + // + object.ArrowColor(style.clr); + object.ArrowWidth(style.width); + } + + /** + * Apply Patterns Style ... + * + * @param object: reference pointer to Object ... + */ + void ApplyPivotsStyle( + CArrayObj *&objects // + ) + { + // + if (objects == NULL || + objects.Total() == 0) + { + return; + } + + // + bool has = false; + XPOIStyle iStyle; + string iName = NULL; + XCBarArrowObject *iObj = NULL; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + for (int i = 0; i < objects.Total(); i++) + { + // + iObj = (XCBarArrowObject *)objects.At(i); + iName = iObj.ObjName(); + + // + iDir = + IsSpecifiedValid(iName) && + Contains( + "BULL", + iName // + ) + ? X_DIRECTION_BULLISH + : IsSpecifiedValid(iName) && + Contains( + "BEAR", + iName // + ) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + has = GetPatternStyle(iStyle, iDir); + if (has) + { + // + ApplyPivotStyle( + iObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iObj); + } + } + + // +}; + +// \ No newline at end of file