From 49e19418b50293f33716ccd35b4c48e4915cf8bc Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Fri, 10 Jul 2026 00:35:09 +0330 Subject: [PATCH] Add Template for X121SHDEA ... --- Experts/x-saherelm.x121.shd.backtester.ea.mq5 | 832 ++++++++++++++ X121SHDEA/.gitkeep | 0 X121SHDEA/Backup/.gitkeep | 0 X121SHDEA/Classes/.gitkeep | 0 .../x-saherelm.x121.shd.signaller.class.mq5 | 1015 +++++++++++++++++ ...saherelm.x121.shd.x-poi.detector.class.mq5 | 40 + ...x-saherelm.x121.shd.x-poi.drawer.class.mq5 | 35 + X121SHDEA/Documents/.gitkeep | 0 X121SHDEA/Libraries/.gitkeep | 0 .../Libraries/x-saherelm.x121.shd.lib.mq5 | 135 +++ 10 files changed, 2057 insertions(+) create mode 100644 Experts/x-saherelm.x121.shd.backtester.ea.mq5 create mode 100644 X121SHDEA/.gitkeep create mode 100644 X121SHDEA/Backup/.gitkeep create mode 100644 X121SHDEA/Classes/.gitkeep create mode 100644 X121SHDEA/Classes/x-saherelm.x121.shd.signaller.class.mq5 create mode 100644 X121SHDEA/Classes/x-saherelm.x121.shd.x-poi.detector.class.mq5 create mode 100644 X121SHDEA/Classes/x-saherelm.x121.shd.x-poi.drawer.class.mq5 create mode 100644 X121SHDEA/Documents/.gitkeep create mode 100644 X121SHDEA/Libraries/.gitkeep create mode 100644 X121SHDEA/Libraries/x-saherelm.x121.shd.lib.mq5 diff --git a/Experts/x-saherelm.x121.shd.backtester.ea.mq5 b/Experts/x-saherelm.x121.shd.backtester.ea.mq5 new file mode 100644 index 00000000..7735b6ab --- /dev/null +++ b/Experts/x-saherelm.x121.shd.backtester.ea.mq5 @@ -0,0 +1,832 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ------------------------------------------------- +// Name: X121SHDEABackTester +// Description: Backtester Expert for X121SHD ... +// +// 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 X121SHD BackTester Expert Advisor" +#property strict + +// +#define ShortName "X121SHDEABackTester" + +// +// Importts ... +#include "../Classes/x-saherelm.x-backtester.expert.class.mq5" +#include "../X121SHDEA/Classes/x-saherelm.x121.shd.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 ... +// #endregion +// #endregion + +// #region Local Variables ... +// +// Requirements ... +string eaLogTag; // EA Log Prefix ... +XCBackTesterEA *eaExpert; // EA Expert ... + +// +// Registered Signallers ... +XCX121SHDStrategy1Signaller *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.kiSuperSlowLength = kiSuperSlowLength; + // kiInputs.maFastLength = maFastLength; + // kiInputs.maSlowLength = maSlowLength; + // kiInputs.maSuperSlowLength = maSuperSlowLength; + // 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.showPV = showPV; + // kiInputs.showKIFast = showKIFast; + // kiInputs.showKISlow = showKISlow; + // kiInputs.showKISuperSlow = showKISuperSlow; + // kiInputs.showMaFast = showMaFast; + // kiInputs.showMaSlow = showMaSlow; + // kiInputs.showMaSuperSlow = showMaSuperSlow; + // kiInputs.showKIWave = showKIWave; + // kiInputs.showKIUpper = showKIUpper; + // kiInputs.showKILower = showKILower; + // kiInputs.startCalculationForLastBars = startCalculationForLastBars; + + // + // Instantiate Signaller ... + + // + // X121SHD1 Signaller ... + signaller1 = new XCX121SHDStrategy1Signaller( + _Symbol, + _Period, + 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 ... + // + // + ); + 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/X121SHDEA/.gitkeep b/X121SHDEA/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/X121SHDEA/Backup/.gitkeep b/X121SHDEA/Backup/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/X121SHDEA/Classes/.gitkeep b/X121SHDEA/Classes/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/X121SHDEA/Classes/x-saherelm.x121.shd.signaller.class.mq5 b/X121SHDEA/Classes/x-saherelm.x121.shd.signaller.class.mq5 new file mode 100644 index 00000000..b5dab7de --- /dev/null +++ b/X121SHDEA/Classes/x-saherelm.x121.shd.signaller.class.mq5 @@ -0,0 +1,1015 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCX121SHDSignaller ... +// Description: X121SHD 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 X121SHD Signaller Class" +#property strict + +// +// Imports ... +#include "../Libraries/x-saherelm.x121.shd.lib.mq5" +#include "../../Classes/x-saherelm.x-signaller.class.mq5" +#include "../Classes/x-saherelm.x121.shd.x-poi.detector.class.mq5" +#include "../Classes/x-saherelm.x121.shd.x-poi.drawer.class.mq5" + +// +// Implementation ... + +// +// Base X121SHD base Signaller ... +class XCX121SHDBaseSignaller : public XCBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + CArrayObj drawnObjects; // Drawing Objects Holder ... + XCX121SHDPOIDrawer *poiDrawer; // X121SHD POI Drawer ... + XCX121SHDPOIDetector *poiDetector; // X121XKI POI Detector ... + + // + // Constructor ... + XCX121SHDBaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + 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 // + ) + { + // + poiDrawer = new XCX121SHDPOIDrawer(); + poiDetector = new XCX121SHDPOIDetector(); + } + + // + // Deconstructor ... + ~XCX121SHDBaseSignaller() + { + Destroy(); + } + + // + // Overrides ... + + // + // Actions ... + + /** + * Destroy ... + */ + void Destroy() + { + // + BeforeDestroy(); + + // + delete poiDrawer; + ZeroMemory(poiDrawer); + + // + delete poiDetector; + ZeroMemory(poiDetector); + } + + // + // 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 = 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: + // +}; + +// +// X121SHD Strategy 1 Signaller Class ... +class XCX121SHDStrategy1Signaller : public XCX121SHDBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCX121SHDStrategy1Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + 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 ... + ) : XCX121SHDBaseSignaller("X121SHD1", + _symbol, + _period, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + } + + // + // Deconstructor ... + ~XCX121SHDStrategy1Signaller() + { + // + 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 .... + ); + if (has) + { + iSignal.provider += "_" + iZone.type; + } + } + + // + // 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; + string provider = NULL; + 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(); + + // + // Check Provided By Strategy 1 ... + provider = positions[i].provider; + StringReplace( + provider, + name, + "" // + ); + has = Contains(ToXString(X121_SHD_STRATEGY_1), positions[i].provider); + if (has) + { + // + // Now we Check Exit ... + // if (positions[i].IsLong()) + // { + // has = ExitBullishPOILong(); + // } + // else if (positions[i].IsShort()) + // { + // has = ExitBearishPOIShort(); + // } + + // // + // 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; + bool useSignaller6 = false; + bool useSignaller7 = 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; + bool signaller6HasSignal = false; + bool signaller7HasSignal = 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 ... + // POI ... + if (useSignaller1) + { + // + signaller1HasSignal = Strategy1HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller1HasSignal) + { + // + provider += ToXString(X121_SHD_STRATEGY_1); + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 2 ... + // Breakout POI ... + if (useSignaller2) + { + // // + // signaller2HasSignal = Strategy2HasSignal( + // bar, + // tmpZone, + // targets, + // tmpDir // + // ); + + // + if (signaller2HasSignal) + { + // + provider += ToXString(X121_SHD_STRATEGY_2); + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 3 ... + // Reversal ... + if (useSignaller3) + { + // // + // signaller3HasSignal = Strategy3HasSignal( + // bar, + // tmpZone, + // targets, + // tmpDir // + // ); + + // + if (signaller3HasSignal) + { + // + provider += ToXString(X121_SHD_STRATEGY_3); + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 4 ... + // Continuation ... + if (useSignaller4) + { + // // + // signaller4HasSignal = Strategy4HasSignal( + // bar, + // tmpZone, + // targets, + // tmpDir // + // ); + + // + if (signaller4HasSignal) + { + // + provider += ToXString(X121_SHD_STRATEGY_4); + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 5 ... + // Exhaustion ... + if (useSignaller5) + { + // // + // signaller5HasSignal = Strategy5HasSignal( + // bar, + // tmpZone, + // targets, + // tmpDir // + // ); + + // + if (signaller5HasSignal) + { + // + provider += ToXString(X121_SHD_STRATEGY_5); + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 6 ... + // Trend Exhaustion ... + if (useSignaller6) + { + // // + // signaller6HasSignal = Strategy6HasSignal( + // bar, + // tmpZone, + // targets, + // tmpDir // + // ); + + // + if (signaller6HasSignal) + { + // + provider += ToXString(X121_SHD_STRATEGY_6); + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 7 ... + // Supply and Demand ... + if (useSignaller7) + { + // // + // signaller7HasSignal = Strategy7HasSignal( + // bar, + // tmpZone, + // targets, + // tmpDir // + // ); + + // + if (signaller7HasSignal) + { + // + provider += ToXString(X121_SHD_STRATEGY_7); + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Summarize Signallers Result ... + result = signaller1HasSignal || + signaller2HasSignal || + signaller3HasSignal || + signaller4HasSignal || + signaller5HasSignal || + signaller6HasSignal || + signaller7HasSignal; + + // + // 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); + if (result) + { + zone.type = "" + provider; + } + + // + // 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; + } + + // #region Custom Signal Strategies ... + /** + * Check Bar Has Signal Based on Strategy 1 ... + * + * @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; + } + + // + int barIndex = bar.Index() + 1; + + // + // Retrieve Base Conditions ... + bool isBullish = false; + bool isBearish = false; + + // + // Validate Conditions ... + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + // Do Validation and Filtering Market Structure if required ... + + // + // Check and Prepare Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + result = HasDirection(dir); + if (!result) + { + return result; + } + + // + // Prepare Zone ... + + // + result = + result && + zone.IsValid() && + HasDirection(dir); + + // + return result; + } + // #endregion + + // +}; + +// diff --git a/X121SHDEA/Classes/x-saherelm.x121.shd.x-poi.detector.class.mq5 b/X121SHDEA/Classes/x-saherelm.x121.shd.x-poi.detector.class.mq5 new file mode 100644 index 00000000..ad2e443e --- /dev/null +++ b/X121SHDEA/Classes/x-saherelm.x121.shd.x-poi.detector.class.mq5 @@ -0,0 +1,40 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCX121SHDPoiDetector ... +// Description: X121SHD 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 X121SHD 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" + +// +// Definitions ... + +// +// Implementation ... +class XCX121SHDPOIDetector : public XCMarketPatternDetector +{ + + // +}; + +// \ No newline at end of file diff --git a/X121SHDEA/Classes/x-saherelm.x121.shd.x-poi.drawer.class.mq5 b/X121SHDEA/Classes/x-saherelm.x121.shd.x-poi.drawer.class.mq5 new file mode 100644 index 00000000..cf154154 --- /dev/null +++ b/X121SHDEA/Classes/x-saherelm.x121.shd.x-poi.drawer.class.mq5 @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCX121SHDPoiDrawer ... +// Description: X121SHD 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 X121SHD POI Drawer Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" + +// +// Implementation ... +class XCX121SHDPOIDrawer : public XCPOIDrawer +{ + + // +}; + +// \ No newline at end of file diff --git a/X121SHDEA/Documents/.gitkeep b/X121SHDEA/Documents/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/X121SHDEA/Libraries/.gitkeep b/X121SHDEA/Libraries/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/X121SHDEA/Libraries/x-saherelm.x121.shd.lib.mq5 b/X121SHDEA/Libraries/x-saherelm.x121.shd.lib.mq5 new file mode 100644 index 00000000..724e995c --- /dev/null +++ b/X121SHDEA/Libraries/x-saherelm.x121.shd.lib.mq5 @@ -0,0 +1,135 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Library +// ------------------------------------------------- +// Name: XCX121SHDLib ... +// Description: X121SHD Library ... +// +// +// 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 X121SHD Library" +#property strict + +// +// Imports ... +#include "../../Libraries/x-saherelm.common.lib.mq5" + +// +// Enums ... + +// #region SHDStrategies ... +enum X121SHDStrategies +{ + X121_SHD_STRATEGY_UNKNOWN = 0, + X121_SHD_STRATEGY_1 = 1, + X121_SHD_STRATEGY_2 = 2, + X121_SHD_STRATEGY_3 = 3, + X121_SHD_STRATEGY_4 = 4, + X121_SHD_STRATEGY_5 = 5, + X121_SHD_STRATEGY_6 = 6, + X121_SHD_STRATEGY_7 = 7, +}; +bool IsXValid(X121SHDStrategies value) +{ + return value != X121_SHD_STRATEGY_UNKNOWN; +} +string ToXString(X121SHDStrategies value) +{ + // + string result = NULL; + + // + if (IsXValid(value)) + { + // + switch (value) + { + // + case X121_SHD_STRATEGY_1: + result = "1"; + break; + // + case X121_SHD_STRATEGY_2: + result = "2"; + break; + // + case X121_SHD_STRATEGY_3: + result = "3"; + break; + // + case X121_SHD_STRATEGY_4: + result = "4"; + break; + // + case X121_SHD_STRATEGY_5: + result = "5"; + break; + // + case X121_SHD_STRATEGY_6: + result = "6"; + break; + // + case X121_SHD_STRATEGY_7: + result = "7"; + break; + } + } + + // + return result; +} +X121SHDStrategies ToX121SHDStrategy(string value) +{ + // + X121SHDStrategies result = X121_SHD_STRATEGY_UNKNOWN; + + // + if (IsXValid(value)) + { + // + if (value == ToXString(X121_SHD_STRATEGY_1)) + { + result = X121_SHD_STRATEGY_1; + } + else if (value == ToXString(X121_SHD_STRATEGY_2)) + { + result = X121_SHD_STRATEGY_2; + } + else if (value == ToXString(X121_SHD_STRATEGY_3)) + { + result = X121_SHD_STRATEGY_3; + } + else if (value == ToXString(X121_SHD_STRATEGY_4)) + { + result = X121_SHD_STRATEGY_4; + } + else if (value == ToXString(X121_SHD_STRATEGY_5)) + { + result = X121_SHD_STRATEGY_5; + } + else if (value == ToXString(X121_SHD_STRATEGY_6)) + { + result = X121_SHD_STRATEGY_6; + } + else if (value == ToXString(X121_SHD_STRATEGY_7)) + { + result = X121_SHD_STRATEGY_7; + } + } + + // + return result; +} +// #endregion + +// \ No newline at end of file