/////////////////////////////////////////////////////// // // SaherElm IT Center XCATB MQL5 Expert Advisor // ------------------------------------------------- // Name: XCAEA // Description: an Exper Advisor which used XCATB // // 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 description "EA based on X121 XCATB indicator" #property strict // // Include Common Library ... #include "../Classes/x-saherelm.x-alert.class.mq5" #include "../Classes/x-saherelm.x-trade.class.mq5" #include "../Classes/x-saherelm.x-volume.class.mq5" #include "../Helpers/x-saherelm.x121.xcatb.helper.mq5" #include "../Libraries/x-saherelm.common.lib.mq5" #include "../Libraries/x-saherelm.x121.xcatb.lib.mq5" #include "../XCAEA/Classes/xcaea.x-trade.manager.class.mq5" // #define ShortName "XCATB_EA" // // Inputs ... // // Common ... input group "Common"; input long eaMagicNumber = 78692110; // Magic Number input int eaSlippage = 10; // Slippgae input string eaLogSuffix = ""; // Log Suffix // // Detector ... input group "Detector"; // // Validating ... input group "Validations"; input bool eaForceHasSwing = false; // Force Blocks to Have Swing input bool eaForceObBarType = false; // Force Block Has Reversal Bar input bool eaForceOBFVGBarType = false; // Force FVG Has Same Bars input bool eaForceHasFLiquidity = false; // Force Blocks to Have Following Liquidity input bool eaForceHasRLiquidity = false; // Force Blocks to Have Reversal Liquidity input bool eaValidateGapSequence = false; // Validate Block's Gap Sequence input bool eaValidateBlockEdgeBreakout = false; // Validate Block's Edge Breakout // // Filtering ... input group "Filters"; input bool eaFilterBasedOnPV = false; // Filter Based on Peak and Vale input bool eaFilterBasedOnSar = false; // Filter Based on Sar input bool eaFilterBasedOnRSI = false; // Filter Based on RSI input bool eaFilterBasedOnADX = false; // Filter Based on ADX input bool eaFilterBasedOnATR = false; // Filter Based on ATR input bool eaFilterBasedOnTrend = false; // Filter Based on Trend input bool eaFilterBasedOnDelta = false; // Filter Based on Delta input bool eaFilterBasedOnVolume = false; // Filter Based on Volume input bool eaFilterBasedOnSignalBar = false; // Filter Based on Signal Bar input bool eaFilterBasedOnHKSignalBar = false; // Filter Based on Hiken Ashi Signal Bar // // Signal ... input group "Signal"; input int eaSignalR2R = 3; // Risk Reward Ratio input double eaSLAtrMultiplier = 0.5; // ATR Multiplier for SL // // Volume ... input group "Volume"; input ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect = X_VOLUME_EQUITY; // 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 = 0.5; // Constant Percent of Balance Per Trade input double eaConstantBalance = 0.0; // Constant Balance for Calculations // // Management ... input group "Management"; input bool eaAllowTrade = true; // Allow Trade on Signals input bool eaAllowLongs = true; // Allow Long Trades input bool eaAllowShorts = true; // Allow Short Trades input ENUM_XCAEA_TRADE_RESTRICTION_PERIOD eaRestrictionsPeriod = XCAEA_TRADE_RESTRICATION_NONE; // Trade Restrictions Period input int eaMaxAllowedTPs = 0; // Max Allowed TP(s) per Day input int eaMaxAllowedSLs = 0; // Max Allowed SL(s) per Day input int eaMaxAllowedTrades = 0; // Max Allowed Trades per Day input int eaMaxAllowedPositions = 5; // Max Allowed Same Time Trades input double eaMaxAllowedSpread = 25; // Max Allowed Spread For Trade input double eaMaxAllowedDrawdownFactor = 0.3; // Max Allowed DrawDown for Trade input string eaCloseAllOpenTradesAt = ""; // Close All Open Trades per Day At Specified Time // // Alert ... // Here we Provider All Requirements for // Configuring Alert Provider ... input group "Alert"; input bool eaEnableAlerts = true; // Enable Alerts input bool eaLogAlerts = true; // Log Alerts input bool eaMailAlerts = false; // Mail Alerts input bool eaPushAlerts = true; // Push Alerts input bool eaTerminalAlerts = true; // Terminal Alerts // // Time Report ... input group "Reports"; input bool eaReportNewMonths = false; // Report New Month input bool eaReportNewWeeks = false; // Report New Weeks input bool eaReportNewDays = true; // Report New Days input bool eaReportNewHours = false; // Report New Hours input bool eaReportTrades = true; // Report Trades input bool eaReportSignals = true; // Report Signals input bool eaReportProtector = true; // Report Protector Actions input bool eaReportAfterTradesBalance = true; // Report Balance after a Trade Finished // // Variables ... // XCAlert *eaAlert; XCTrade *eaTrade; XSignal eaSignal; XCVolume *eaVolume; X121XCatbInputs eaInputs; XCX121XCatbHelper *eaHelper; XBarTracker eaBarTraker; XTimeTracker eaTimeTracker; XCXCAEATradeManager *eaTradeManager; XCAEAStrategyConditions eaConditions; // XTriggerBlock eaTB; // CArrayObj *eaObjects; // string eaTag = ""; // // Event Handlers ... // // Initialization ... int OnInit() { // // Validate Inputs and Required Parameters // for EA to Works fine ... if (!ValidateInputs()) { return INIT_PARAMETERS_INCORRECT; } // // Initial Requirements ... InitRequirements(); // // Initialize Volume Manger ... if (!InitVolume()) { return INIT_FAILED; } // 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 // // eaObjects.Clear(); // delete eaHelper; ZeroMemory(eaHelper); // delete eaAlert; ZeroMemory(eaAlert); // delete eaTrade; ZeroMemory(eaTrade); // delete eaVolume; ZeroMemory(eaVolume); // eaSignal.Clean(); eaBarTraker.Clean(); eaConditions.Clean(); eaTimeTracker.Clean(); // DestroyTimer(); } // // On Tick Handler ... void OnTick() { // HandleTimeReport(); // // Handle Position Management / Protections ... // eaTradeManager.Manage(); // // // eaSignal.Clean(); // eaConditions.Clean(); // // Check Bar Processing ... if (!eaBarTraker.CanProcessBar()) { return; } // bool has = false; // // Retrieve Bars ... // XOHCL zBar; // XOHCL cBar; // has = zBar.Init( // _Symbol, // _Period, // 0 // // ); // has = // has && // zBar.GetPreviousBar(cBar); // if (!has) // { // // // zBar.Clean(); // cBar.Clean(); // // // return; // } // // double bid = GetBid(zBar.symbol); // // XTriggerBlock iTB; // has = GetNewestX121TriggerBlock( // _Symbol, // _Period, // iTB // // ); // if (has) // { // // // // Check Newest TB is Newer Than Exists TB ... // bool canPass = // !eaTB.IsValid() // ? true // : iTB.ToIndex() < eaTB.ToIndex(); // if (canPass) // { // // // eaTB = iTB; // eaSignal = iTB.signal; // // // // Prepare eaConditions if Reuqired ... // } // } // // has = eaSignal.IsValid(); // if (has) // { // // // // Here we ensure which has a New Signal and must // // prepare and Execute it ... // Print("new Signal Detected ..."); // } // // eaTB.Clean(); // zBar.Clean(); // cBar.Clean(); // eaSignal.Clean(); // eaConditions.Clean(); } // // Handle On Trade Event ... void OnTrade() { eaTrade.HandleOnTrade(); } // // On Timer ... void OnTimer() { } // // Chart Event Handler ... void OnChartEvent( const int id, const long &lparam, const double &dparam, const string &sparam // ) { } // // Event Listeners ... /** * Handle StopLoss Triggered Positions ... * * @param deal: XDeal instance ... */ void OnStopLossTriggered(const XDeal &deal) { eaTradeManager.HandleSL(deal); } /** * Handle Take Profit Triggered Positions ... * * @param deal: XDeal instance ... */ void OnTakeProfitTriggered(const XDeal &deal) { eaTradeManager.HandleTP(deal); } /** * 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 // ) { eaTradeManager.HandleForceClose(position); } /** * Handle Position Partially Closed Event ... * * @param ticket: ULONG ... * @param profit: double ... * @param comment: string ... */ void OnPositionPartiallyClosed( const ulong ticket, const double profit, const string comment // ) { eaTradeManager.HandlePartiallyClosed( ticket, profit, comment // ); } /** * Handle Deals Changes ... * * @param count: Integer, Number of Changes ... */ void OnDealsChanged(int count) { } /** * Handle Orders Changes ... * * @param count: Integer, Number of Changes ... */ void OnOrdersChanged(int count) { } /** * Handle Positions Changes ... * * @param count: Integer, Number of Changes ... */ void OnPositionsChanged(int count) { } // // Custom Functions ... /** * Validate all Inputs of Expert Adviser ... * * @return ( bool ) */ bool ValidateInputs() { // bool result = false; // string errMessage = ""; // bool isCommonValid = ( // eaSlippage > 0 && eaMagicNumber > 0 // ); 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(); } /** * Initial Volume Manager Class Based on Given Configuration ... * * @return ( bool ) */ bool InitVolume() { // bool result = false; // eaVolume = new XCVolume(); // result = eaVolume.Init( eaVolumeSelect, eaStaticVoluem, eaDynamicVolumeStepBalance, eaDynamicVolumeStepVolume, eaConstantRiskBalance, eaConstantPercent, eaConstantBalance // ); // return result; } /** * Initial Requirements of EA ... */ void InitRequirements() { // // Initial Bar Tracker ... eaBarTraker.Init( _Symbol, _Period // ); // // Preparing Tags ... eaTag = (IsValid(eaLogSuffix) ? eaLogSuffix + "_" : "") + ShortName; // eaAlert = new XCAlert(); eaAlert.SetPrefix(eaLogSuffix); eaAlert.SetLogAlerts(eaLogAlerts); eaAlert.SetMailAlerts(eaMailAlerts); eaAlert.SetPushAlerts(eaPushAlerts); eaAlert.SetEnableAlerts(eaEnableAlerts); eaAlert.SetTerminalAlerts(eaTerminalAlerts); // // Objects ... eaObjects = new CArrayObj(); // // Configure XCA ... eaInputs.Default(); // // Hide all Visible Buffers ... eaInputs.Hide(); // // we Can make Show all requirements here ... // eaInputs.showATRBand = true; // // // // Signal ... // eaInputs.signalR2R = eaSignalR2R; // eaInputs.slAtrMultiplier = eaSLAtrMultiplier; // // // // Set Validators ... // eaInputs.forceHasSwing = eaForceHasSwing; // eaInputs.forceObBarType = eaForceObBarType; // eaInputs.forceOBFVGBarType = eaForceOBFVGBarType; // eaInputs.forceHasFLiquidity = eaForceHasFLiquidity; // eaInputs.forceHasRLiquidity = eaForceHasRLiquidity; // eaInputs.validateGapSequence = eaValidateGapSequence; // eaInputs.validateBlockEdgeBreakout = eaValidateBlockEdgeBreakout; // // // // Set Filters ... // eaInputs.filterBasedOnPV = eaFilterBasedOnPV; // eaInputs.filterBasedOnSar = eaFilterBasedOnSar; // eaInputs.filterBasedOnRSI = eaFilterBasedOnRSI; // eaInputs.filterBasedOnADX = eaFilterBasedOnADX; // eaInputs.filterBasedOnATR = eaFilterBasedOnATR; // eaInputs.filterBasedOnTrend = eaFilterBasedOnTrend; // eaInputs.filterBasedOnDelta = eaFilterBasedOnDelta; // eaInputs.filterBasedOnVolume = eaFilterBasedOnVolume; // eaInputs.filterBasedOnSignalBar = eaFilterBasedOnSignalBar; // eaInputs.filterBasedOnHKSignalBar = eaFilterBasedOnHKSignalBar; // // // // Alerts ... // // eaInputs.alertPrefix = eaTag; // // eaInputs.logAlerts = eaLogAlerts; // // eaInputs.pushAlerts = eaMailAlerts; // // eaInputs.mailAlerts = eaPushAlerts; // // eaInputs.terminalAlerts = eaTerminalAlerts; // // eaHelper = new XCX121XCatbHelper(); // bool isInited = eaHelper.Init( // _Symbol, // _Period, // eaInputs // // ); // // // // EA Trade ... // eaTrade = new XCTrade( // eaSlippage, // eaMagicNumber, // eaMaxAllowedSpread, // eaMaxAllowedPositions, // eaMaxAllowedDrawdownFactor // // ); // eaTrade.AddOnStopLossEventHandler(OnStopLossTriggered); // eaTrade.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); // eaTrade.AddOnForceClosePositionEventHandler(OnPositionForceClosed); // eaTrade.AddOnPartialClosePositionEventHandler(OnPositionPartiallyClosed); // // // // EA Trae Manager ... // eaTradeManager = new XCXCAEATradeManager( // eaTrade // // ); // eaTradeManager.SaveTrades(true); // eaTradeManager.SetAlertEnableAlerts(eaEnableAlerts); // eaTradeManager.SetAlertPrefix(eaTag); // eaTradeManager.SetAlertLogAlerts(eaLogAlerts); // eaTradeManager.SetAlertMailAlerts(eaMailAlerts); // eaTradeManager.SetAlertPushAlerts(eaPushAlerts); // eaTradeManager.SetAlertTerminalAlerts(eaTerminalAlerts); // // // // Setting Trade Reports ... // eaTradeManager // .SetTradeReports( // eaReportTrades, // eaReportSignals, // eaReportProtector, // eaReportAfterTradesBalance // // ); // // // // Setting Trade Permissions ... // eaTradeManager // .SetTradePermissions( // eaAllowTrade, // eaAllowLongs, // eaAllowShorts // // ); // // // // Setting Trade Restrictions ... // eaTradeManager // .SetTradeRestrictions( // eaRestrictionsPeriod, // eaMaxAllowedTPs, // eaMaxAllowedSLs, // eaMaxAllowedTrades // // ); } /** * Handling Time Reporting ... */ void HandleTimeReport() { // if (eaAlert == NULL) { return; } // // Monthly Report .... if (eaReportNewMonths && eaTimeTracker.IsNewMonth()) { // string msg = "New Month ..."; // eaAlert.Alert(msg); } // // Weekly Report .... if (eaReportNewWeeks && eaTimeTracker.IsNewWeek()) { // string msg = "New Week ..."; // eaAlert.Alert(msg); } // // Daily Report .... if (eaReportNewDays && eaTimeTracker.IsNewDay()) { // string msg = "New Day ..."; // eaAlert.Alert(msg); } // // Hourly Report .... if (eaReportNewHours && eaTimeTracker.IsNewHour()) { // string msg = "New Hour ..."; // eaAlert.Alert(msg); } } // // Apply Signal Targets ... // void ApplySignalTargets(XSignal &signal) // { // // // bool has = signal.IsValid(); // if (!has) // { // return; // } // // // // Clean Signal Targets ... // Clean(signal.targets); // // // // Calculate Requirements ... // double r2r = 1; // // maxAllowedR2R > 0 // // ? maxAllowedR2R // // : 1; // double risk = signal.GetRisk(); // double reward = risk * r2r; // // // double isLong = IsLong(signal.type); // // // // Handling Signal TP ... // signal.tp = // isLong // ? signal.entry + reward // : signal.entry - reward; // // // // Try to Apply Money Management ... // // // if (r2r <= 1) // { // return; // } // // // // XTarget iTarget; // // // // // // Partial Close 0.5 of Position on Reward 1 ... // // reward = risk * 1; // // iTarget.target = // // isLong // // ? signal.entry + reward // // : signal.entry - reward; // // iTarget.volumeMultiplier = 0.5; // // // // // AddRef(iTarget, signal.targets); // // iTarget.Clean(); // // // // // if (r2r <= 2) // // { // // return; // // } // // // // Making Loop ... // // for (int i = 2; i < ((int)r2r - 1); i++) // // { // // // // // iTarget.Clean(); // // // // // reward = i * risk; // // iTarget.target = // // isLong // // ? signal.entry + reward // // : signal.entry - reward; // // iTarget.volumeMultiplier = 1 / (r2r - 2); // // // // // AddRef(iTarget, signal.targets); // // } // // // // Sort Targets ... // ENUM_X_DIRECTION sortingDir = // isLong // ? X_DIRECTION_BULLISH // : X_DIRECTION_BEARISH; // ApplySortOnTargets( // sortingDir, // signal.targets // // ); // } ///////////////////////////////////////////////////// // static XTriggerBlock mX121TriggerBlocks[]; // int HasX121TriggerBlocks() { return HasChild(mX121TriggerBlocks); } // int CountX121TriggerBlocks() { return ArraySize(mX121TriggerBlocks); } // void CleanX121TriggerBlocks(int maxAllowed = 0) { // if (maxAllowed <= 0) { Clean(mX121TriggerBlocks); } else if (maxAllowed > 0) { // CleanupArray( mX121TriggerBlocks, maxAllowed // ); } } // bool GetNewestX121TriggerBlock( string forSymbol, ENUM_TIMEFRAMES forPeriod, XTriggerBlock &tb // ) { // bool result = false; // tb.Clean(); // result = IsValid(forSymbol) && IsValid(forPeriod) && HasX121TriggerBlocks(); if (!result) { return result; } // // Loop Through Trigger Blocks to Find Filtered Newest ... int count = CountX121TriggerBlocks(); for (int i = 0; i < count; i++) { // bool canSet = !tb.IsValid() ? true : tb.ToIndex() < mX121TriggerBlocks[i].ToIndex(); if (canSet) { tb = mX121TriggerBlocks[i]; } } // result = tb.IsValid(); if (!result) { tb.Clean(); } // return result; } /////////////////////////////////////////////////// // // Add Trigger Block to Collection // and Cleanup Unuseds ... AddRef( tb, mX121TriggerBlocks // ); CleanX121TriggerBlocks(20);