Files
MQL5Data/Experts/x-saherelm.x-expert.ea.v2.mq5
T
2026-07-10 04:24:32 +03:30

772 lines
18 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Expert Advisor
// -------------------------------------------------
// Name: XBaseEA
// Description: Base Expert Advisor V2 ...
//
// 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 "2.00"
#property icon "../Images/SaherElm_Logo_Color.ico"
#property description "SaherElm Base Expert Advisor"
#property strict
// #region Imports ...
#include "../Classes/x-saherelm.base.class.mq5"
#include "../Classes/x-saherelm.session-detector.class.mq5"
#include "../Classes/x-saherelm.x-alert.class.mq5"
#include "../Classes/x-saherelm.x-chart.helper.class.mq5"
#include "../Classes/x-saherelm.x-guard.class.mq5"
#include "../Classes/x-saherelm.x-restrictions.class.mq5"
#include "../Classes/x-saherelm.x-target.class.mq5"
#include "../Classes/x-saherelm.x-trade-manager.class.mq5"
#include "../Classes/x-saherelm.x-trade.class.mq5"
#include "../Classes/x-saherelm.x-volume.class.mq5"
// #endregion
// #region Inputs ...
input group "Common";
input long eaMagicNumber = 1694056; // Magic Number
input int eaSlippage = 10; // Slippgae
input string eaLogSuffix = ""; // Log Suffix
//
// Management ...
input group "Management";
input bool eaAllowGuards = false; // Allow Guards
input bool eaAllowTrade = true; // Allow Trade on Signals
input bool eaAllowLongs = true; // Allow Long Trades
input bool eaAllowShorts = true; // Allow Short Trades
input double eaMaxAllowedDrawdownFactor = 0.3; // Max Allowed DrawDown for Trade
//
// 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
//
// Alert ...
input group "Alert";
input bool eaEnableAlerts = true; // Enable Alerts
input bool eaSaveAlerts = true; // Save Alerts
input bool eaLogAlerts = true; // Log Alerts
input bool eaMailAlerts = false; // Mail Alerts
input bool eaPushAlerts = true; // Push Alerts
input bool eaTerminalAlerts = false; // Terminal Alerts
//
// Reports ...
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 eaReportRestrictions = true; // Report Restrictions
input bool eaReportProtector = true; // Report Protector Actions
input bool eaReportAfterTradesBalance = true; // Report Balance after a Trade Finished
//
// Collector ...
input group "Collector";
input bool eaSaveTrades = true; // Save Trades
input bool eaSaveSignals = true; // Save Signals
input bool eaSaveWins = true; // Save Winning Conditions
input bool eaSaveLosts = true; // Save Lost Conditions
input bool eaSaveRestrictions = true; // Save Restriction Reports
// #endregion
// #region Configurable Documents ...
bool eaEnableAnalysis = true; // Most Important Flag for Enable Analysis in EA ...
bool processTicksOnlyOnNewBars = false; // Processing Ticks only on new Bars ...
ENUM_X_SESSION_TYPE eaAllowedSessions[]; // Allowed Sessions for Analysis ...
ENUM_X_SESSION_OVERLAP_TYPE eaAllowedOverlaps[]; // Allowed Overlaps for Analysis ...
// #endregion
// #region Global Variables ...
#define ShortName "XSessionDetectorTestEA"
//
string eaTag; // EA Scoped Tag ...
bool isEaInNewBar = false; // EA Is New Bar ...
//
XCAlert *eaAlert; // EA Scope Alert Handler ...
XCGuard *eaGuard; // EA Scope Guard Handler ...
XCTrade *eaTrader; // EA Scope Trade Handler ...
XCVolume *eaVolume; // EA Scope Voluem Handler ...
XCTarget *eaTarget; // EA Scope Target Handler ...
XBarTracker eaBarTracker; // EA Scope Bar Tracker ...
XTimeTracker eaTimeTracker; // EA Scope Time Tracker ...
XCRestrictions *eaRestrictions; // EA Scope Restrictions Handler ...
XCTradeManager *eaTradeManager; // EA Scope Trade Manager Handler ...
XCSessionDetector *eaSessionDetector; // EA Scope Session Detector ...
// #endregion
// #region Global Event Handlers ...
/**
* Initialize EA Process ...
*
* @return ( int )
*/
int OnInit()
{
//
bool result = true;
//
if (!ValidateInputs())
{
return INIT_PARAMETERS_INCORRECT;
}
//
// Initialize Timer ...
if (!InitTimer())
{
return INIT_FAILED;
}
//
// Configure Dynamic Variables ...
ConfigureEA();
//
result = InitializeRequirements();
if (!result)
{
return INIT_FAILED;
}
//
return INIT_SUCCEEDED;
}
/**
* Handle Tick for Processing ...
*/
void OnTick()
{
//
// Perform Session Detector Process ...
eaSessionDetector.Process();
//
// Perform Restrictions Process ...
eaRestrictions.Process();
//
// Check if Is New Bar ...
isEaInNewBar = eaBarTracker.IsNewBar();
//
// Check Analysis Enabled ...
if (eaEnableAnalysis)
{
//
// Check Bar Tracker ...
if (processTicksOnlyOnNewBars)
{
//
// Check New Bar or not ...
if (!isEaInNewBar)
{
return;
}
}
//
// Do Analysis ...
// TODO: Implement this ...
}
}
/**
* Handle On Trade Processing ...
*/
void OnTrade()
{
//
// Calling Event Handler ...
eaTrader.HandleOnTrade();
}
/**
* Handle On Timer Processing ...
*/
void OnTimer()
{
}
/**
* De Initialize Expert ...
*
* @param reason: int, DeInitialization 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
*
*/
void OnDeinit(const int reason)
{
//
// Destroy Timer ...
// If Initialized ...
DestroyTimer();
//
// Cleaning Time Tracker ...
eaTimeTracker.Clean();
//
// Cleanup Resources ...
ZeroMemory(eaAlert);
ZeroMemory(eaGuard);
ZeroMemory(eaTrader);
ZeroMemory(eaVolume);
ZeroMemory(eaTarget);
ZeroMemory(eaTradeManager);
ZeroMemory(eaRestrictions);
ZeroMemory(eaSessionDetector);
}
/**
* Handle On Chart Event Processing ...
* @param id: int, Specified Event ID ...
* @param lparam: long, type event parameter
* @param dparam: double, type event parameter
* @param sparam: string, type event parameter
*/
void OnChartEvent(
const int id,
const long &lparam,
const double &dparam,
const string &sparam //
)
{
}
// #endregion
// #region Custom Actions ...
/**
* 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;
}
/**
* Configure EA Commons ...
*/
void ConfigureEA()
{
//
// Configure Sessions ...
//
// Configure Overlaps ...
Add(
X_OVERLAP_LONDON_NEWYORK,
eaAllowedOverlaps //
);
//
// Startup eaAnalysis State ...
int sessionsCount = ArraySize(eaAllowedSessions);
int overlapsCount = ArraySize(eaAllowedOverlaps);
//
eaEnableAnalysis =
!IsValidSize(sessionsCount) &&
!IsValidSize(overlapsCount);
}
/**
* Initial Requirements of EA ...
*
* @return ( bool )
*/
bool InitializeRequirements()
{
//
bool result = false;
//
// Preparing Tags ...
eaTag =
(IsXValid(eaLogSuffix)
? eaLogSuffix + "_"
: "") +
ShortName;
// #region Initializing Bar Tracker ...
result = eaBarTracker.Init(
_Symbol,
_Period //
);
if (!result)
{
return result;
}
// #endregion
// #region Alert ...
eaAlert = new XCAlert();
eaAlert.SetPrefix(eaLogSuffix);
eaAlert.SetLogAlerts(eaLogAlerts);
eaAlert.SetMailAlerts(eaMailAlerts);
eaAlert.SetPushAlerts(eaPushAlerts);
eaAlert.SetSaveAlerts(eaSaveAlerts);
eaAlert.SetEnableAlerts(eaEnableAlerts);
eaAlert.SetTerminalAlerts(eaTerminalAlerts);
result = eaAlert != NULL;
if (!result)
{
return result;
}
// #endregion
// #region Session Detector ...
eaSessionDetector = new XCSessionDetector(
eaAlert, // Alert ...
true, // Use Server Time ...
0 // Timezone Offset ...
);
//
// Register Event Handlers ...
eaSessionDetector.AddOnSessionStartHandler(OnSessionStartHandler);
eaSessionDetector.AddOnOverlapStartHandler(OnOverlapStartHandler);
eaSessionDetector.AddOnSessionStateChangeHandler(OnSessionStateChangeHandler);
// #endregion
// #region Volume Provider ...
eaVolume = new XCVolume();
result = eaVolume.Init(
eaVolumeSelect,
eaStaticVoluem,
eaDynamicVolumeStepBalance,
eaDynamicVolumeStepVolume,
eaConstantRiskBalance,
eaConstantPercent,
eaConstantBalance //
);
if (!result)
{
return result;
}
// #endregion
// #region Trader ...
eaTrader = new XCTrade(
eaSlippage,
eaMagicNumber,
0,
0,
eaMaxAllowedDrawdownFactor //
);
//
eaTrader.AddOnDealsChangedEventHandler(OnDealsChanged);
eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered);
eaTrader.AddOnOrdersChangedEventHandler(OnOrdersChanged);
eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered);
eaTrader.AddOnModifyPositionEventHandler(OnPositionModified);
eaTrader.AddOnPositionsChangedEventHandler(OnPositionsChanged);
eaTrader.AddOnTradeStateChangedEventHandler(OnTradeStateChanged);
eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed);
eaTrader.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed);
// #endregion
// #region Guard ...
eaGuard = new XCGuard(
eaAlert,
eaTrader //
);
//
eaGuard.onGuardEventListener = OnGuardedTriggered;
// #endregion
// #region Target ...
eaTarget = new XCTarget(
eaTrader,
eaAlert);
// #endregion
// #region Trae Manager ...
eaTradeManager = new XCTradeManager(
eaAlert,
eaTrader,
eaVolume,
eaGuard,
eaTarget //
);
//
eaTradeManager.checkForGuardEventListener = CheckForGuardTriggered;
//
eaTradeManager.SaveWins(eaSaveWins);
eaTradeManager.SaveLosts(eaSaveLosts);
eaTradeManager.SaveTrades(eaSaveTrades);
eaTradeManager.SaveSignals(eaSaveSignals);
eaTradeManager.SaveRestrictions(eaSaveRestrictions);
//
// Setting Trade Reports ...
eaTradeManager
.SetTradeReports(
eaReportTrades,
eaReportSignals,
eaReportProtector,
eaReportRestrictions,
eaReportAfterTradesBalance //
);
//
// Setting Trade Permissions ...
eaTradeManager
.SetTradePermissions(
eaAllowTrade,
eaAllowLongs,
eaAllowShorts //
);
// #endregion
// #region Restrictions Handler ...
eaRestrictions = new XCRestrictions();
//
// Configure Restrictions ...
// TODO: Refactor Restrictions Configurations as Input ...
eaRestrictions.SetAllowedLosesInRestrictions(2);
eaRestrictions.SetAllowedTradesInRestrictions(2);
eaRestrictions.SetRestrictionsPeriodMultiplier(2);
eaRestrictions.SetRestrictionsPeriod(X_TRADE_RESTRICATION_DAILY);
//
// Register Event Handlers ...
eaRestrictions.AddRestrictionsEndEventHandler(OnRestrictionsEnd);
eaRestrictions.AddRestrictionsStartEventHandler(OnRestrictionsStart);
// #endregion
//
result = eaSessionDetector != NULL;
if (!result)
{
return result;
}
//
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();
}
// #endregion
// #region Custom Event Handlers ...
/**
* Check For Guard ...
* XCHuard
*
* @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 CheckForGuardTriggered(
XGuard &guards[],
XPosition &positions[],
int barIndex = 0 //
)
{
return 0;
}
/**
* Handle Guard Events ...
* XCHuard
*
* @param action: ENUM_X_GUARD_ACTIONS
* @param positions: XPosition[]
*/
void OnGuardedTriggered(
ENUM_X_GUARD_ACTIONS action,
XPosition &positions[] //
)
{
}
/**
* Handle Session Start Event ...
* XCSessionDetector
*
* @param session: ENUM_X_SESSION_TYPE
* @param startTime: datetime
*/
void OnSessionStartHandler(
ENUM_X_SESSION_TYPE session,
datetime startTime //
)
{
Print("Session Started: ", EnumToString(session), " at ", TimeToString(startTime));
}
/**
* Handle Overlap Start Event ...
* XCSessionDetector
*
* @param session: ENUM_X_SESSION_OVERLAP_TYPE
* @param startTime: datetime
*/
void OnOverlapStartHandler(
ENUM_X_SESSION_OVERLAP_TYPE overlap,
datetime startTime //
)
{
//
Print("Overlap Started: ", EnumToString(overlap), " at ", TimeToString(startTime));
//
// Check Over lap Exists in eaSession Everlaps ...
}
/**
* Handle Session State Change Event ...
* XCSessionDetector
*
* @param session: ENUM_X_SESSION_TYPE
* @param state: ENUM_X_SESSION_STATE
*/
void OnSessionStateChangeHandler(
ENUM_X_SESSION_TYPE session,
ENUM_X_SESSION_STATE state //
)
{
Print("Session State Changed: ", EnumToString(session), " State: ", EnumToString(state));
}
/**
* Handle StopLoss Triggered Positions ...
* XCTrade
*
* @param deal: XDeal instance ...
*/
void OnStopLossTriggered(const XDeal &deal)
{
}
/**
* Handle Take Profit Triggered Positions ...
* XCTrade
*
* @param deal: XDeal instance ...
*/
void OnTakeProfitTriggered(const XDeal &deal)
{
}
/**
* Handle Force Close a Position ...
* XCTrade
*
* @param ticket: ULONG ...
* @param position: XPosition instance ...
* @param comment: String ...
*/
void OnPositionForceClosed(
const ulong ticket,
const XPosition &position,
const string comment //
)
{
}
/**
* Handle Deals Changes ...
* XCTrade
*
* @param count: Integer, Number of Changes ...
*/
void OnDealsChanged(int count)
{
}
/**
* Handle Orders Changes ...
* XCTrade
*
* @param count: Integer, Number of Changes ...
*/
void OnOrdersChanged(int count)
{
}
/**
* Handle Positions Changes ...
* XCTrade
*
* @param count: Integer, Number of Changes ...
*/
void OnPositionsChanged(int count)
{
}
/**
* Handle Position Modified ...
* XCTrade
*
* @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 //
)
{
}
/**
* Handle Position Partial Closed ...
* XCTrade
*
* @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 //
)
{
}
/**
* Handle Trade State Changed ...
* XCTrade
*
* @param state: XOnTradeHandlerState instance ...
*/
void OnTradeStateChanged(const XOnTradeHandlerState &state)
{
}
/**
* Handle Restrictions Start Event ...
* XCRestrictions ...
*/
void OnRestrictionsStart()
{
Print("Restrictions Start ...");
}
/**
* Handle Restrictions End Event ...
* XCRestrictions ...
*/
void OnRestrictionsEnd()
{
Print("Restrictions End ...");
}
// #endregion
//