diff --git a/Classes/x-saherelm.x-backtester.expert.class.mq5 b/Classes/x-saherelm.x-backtester.expert.class.mq5 index ca56fba3..8f8e6dfc 100644 --- a/Classes/x-saherelm.x-backtester.expert.class.mq5 +++ b/Classes/x-saherelm.x-backtester.expert.class.mq5 @@ -685,6 +685,7 @@ class XCBackTesterEA : public XCBase // ulong selectedPositionID; + bool showSelectedPositionInfo; // // GUI Event(s) ... @@ -930,7 +931,7 @@ class XCBackTesterEA : public XCBase // // Handle Toggle Show/Hide lblSelectedPositionInfo ... CEdit *iLbl = NULL; - bool isVisible = false; + bool isVisible = showSelectedPositionInfo; int count = selectedPosInfoArr.Total(); if (IsValidSize(count)) { @@ -953,11 +954,12 @@ class XCBackTesterEA : public XCBase // // Update Button Text ... - isVisible = iLbl.IsVisible(); + isVisible = showSelectedPositionInfo; string btnText = isVisible ? "Hide Info" : "Show Info"; btnSelectedPosInfo.Text(btnText); + showSelectedPositionInfo = !showSelectedPositionInfo; } // @@ -1227,7 +1229,7 @@ class XCBackTesterEA : public XCBase // int btnStartY = btnCloseSizeY + 5; - int btnSizeY = btnStartY + 50; + int btnSizeY = btnStartY + 25; // bool isCreated = btnSelectedPosInfo.Create( @@ -1329,6 +1331,16 @@ class XCBackTesterEA : public XCBase iLbl.ColorBorder(clrDarkSlateGray); iLbl.ColorBackground(clrDarkSlateGray); + // + if (showSelectedPositionInfo) + { + iLbl.Show(); + } + else + { + iLbl.Hide(); + } + // selectedPosInfoArr.Add(iLbl); @@ -1360,7 +1372,7 @@ class XCBackTesterEA : public XCBase } // - bool isVisible = iLbl.IsVisible(); + bool isVisible = showSelectedPositionInfo; string btnText = isVisible ? "Hide Info" : "Show Info"; diff --git a/Experts/x-saherelm.backtester.mq5 b/Experts/x-saherelm.backtester.ea.mq5 similarity index 100% rename from Experts/x-saherelm.backtester.mq5 rename to Experts/x-saherelm.backtester.ea.mq5 diff --git a/Experts/x-saherelm.xfima.backtester.ea.mq5 b/Experts/x-saherelm.xfima.backtester.ea.mq5 new file mode 100644 index 00000000..18cb7d97 --- /dev/null +++ b/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -0,0 +1,409 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XBackTester +// Description: a Backtest Tools Strategy Tester +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +//////////////////////////////////////////////////////x +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XBackTester" +#property strict + +// +#define ShortName "XBackTester" + +// +// Imports ... +#include "../Classes/x-saherelm.x-backtester.expert.class.mq5" +#include "../Helpers/x-saherelm.xom1.helper.mq5" + +// +// Definitions ... + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// 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 = false; // Push Alerts +input bool eaTerminalAlerts = false; // Terminal Alerts + +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XCBackTesterEA *eaExpert; // EA Expert ... + +// +// Define Indicators Here ... + +// +// 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; + + // + // 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.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaExpert.AddOnModifyPositionEventHandler(OnPositionModified); + eaExpert.AddOnPositionsChangedEventHandler(OnPositionsChanged); + eaExpert.AddOnTradeStateChangedEventHandler(OnTradeStateChanged); + eaExpert.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + eaExpert.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed); + + // + // Try to Initialize eaExpert ... + bool isInited = eaExpert.HandleOnInit(); + if (!isInited) + { + // + Print(ShortName, ": Initialization Failed ..."); + return INIT_FAILED; + } + + // + 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(); + + // + delete eaExpert; + ZeroMemory(eaExpert); +} + +// +// On Tick Handler ... +void OnTick() +{ + eaExpert.HandleOnTick(); +} + +// +// 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); +} + +// +// 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(); +} + +// +// Trade Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + eaExpert.HandleOnStopLossTriggered(deal); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + eaExpert.HandleOnTakeProfitTriggered(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 // +) +{ + // + eaExpert.HandleOnPositionForceClosed( + ticket, + position, + comment // + ); +} + +/** + * 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); +} + +// \ No newline at end of file