Files
MQL5Data/Experts/x-saherelm.xcaea.ea.mq5
T
2025-05-13 23:17:25 +03:30

943 lines
22 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center XCAEA MQL5 Expert Advisor
// -------------------------------------------------
// Name: XCAEA
// Description: an Exper Advisor which used Panels
//
// 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 "SaherElm XCAEA EA"
#property strict
//
// Imports ...
#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 "../XCAEA/Classes/xcaea.x-trade.manager.class.mq5"
#include "../XCAEA/Signals/xcaea.signaller.class.mq5"
//
#define ShortName "XCAEAEA"
//
// Inputs ...
//
// Common ...
input group "Common";
input long eaMagicNumber = 78692110; // Magic Number
input int eaSlippage = 10; // Slippgae
input string eaLogSuffix = ""; // Log Suffix
input ENUM_TIMEFRAMES eaAnalysisPeriod = PERIOD_H1; // Analysis Period
//
// Symbols ...
//
// -------------------------------------------------------
// ----------
// eaSymbols:
// ----------
// - if EMPTY use Current Symbol;
// - for Multi Symbol use Comma Separated Symbols:
// EURUSDb,XAUUSDb
//
// ------------------
// eaSymbolSessions:
// ------------------
// - if EMPTY use WHOLE Times;
// - for each Symbol use Comma Separated:
// (XEURS1_02:00_14:00),(XEURS2_19:00_23:00)|
// -------------------------------------------------------
input group "Symbols";
input string eaSymbols = ""; // Symbols Description
input string eaSymbolSessions = ""; // Symbols Sessions
//
// 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_DAILY; // Trade Restrictions Period
input int eaMaxAllowedTPs = 2; // Max Allowed TP(s) per Day
input int eaMaxAllowedSLs = 2; // Max Allowed SL(s) per Day
input int eaMaxAllowedTrades = 3; // 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 = false; // Push Alerts
input bool eaTerminalAlerts = false; // 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, Instances ...
XCAlert *eaAlert;
XCTrade *eaTrade;
XSignal eaSignal;
XCVolume *eaVolume;
XTimeTracker eaTimeTracker;
XCXCAEASignaller *eaSignallers[];
XCXCAEATradeManager *eaTradeManager;
XCAEAStrategyConditions eaConditions;
//
string eaTag = "";
//
// Event Handlers ...
//
// Initialization ...
int OnInit()
{
//
// Validate Inputs and Required Parameters
// for EA to Works fine ...
if (!ValidateInputs())
{
return INIT_PARAMETERS_INCORRECT;
}
//
// Initialize Timer ...
if (!InitTimer())
{
return INIT_FAILED;
}
//
// Initial Requirements ...
InitRequirements();
//
// Initialize Volume Manger ...
if (!InitVolume())
{
return INIT_FAILED;
}
//
// Init Succeed ...
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
//
//
ZeroMemory(eaAlert);
ZeroMemory(eaTrade);
ZeroMemory(eaVolume);
//
eaSignal.Clean();
eaConditions.Clean();
eaTimeTracker.Clean();
//
int count = ArraySize(eaSignallers);
for (int i = 0; i < count; i++)
{
//
eaSignallers[i].DeInit();
ZeroMemory(eaSignallers[i]);
}
Clean(eaSignallers);
//
DestroyTimer();
}
//
// On Tick Handler ...
void OnTick()
{
//
int idx = -1;
int count = 0;
bool has = false;
//
HandleTimeReport();
//
// Handle Position Management / Protections ...
eaTradeManager.Manage();
//
eaSignal.Clean();
eaConditions.Clean();
//
double r2r = 4;
string provider = "XCAEA";
datetime cTime = TimeCurrent();
ENUM_POSITION_TYPE type = POSITION_TYPE_BUY;
ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET;
//
bool hasLong = false;
bool hasShort = false;
//
// Checking Signallers ...
has = HasChild(eaSignallers);
if (!has)
{
return;
}
//
int signallersCount = ArraySize(eaSignallers);
for (int is = 0; is < signallersCount; is++)
{
//
// Start Calculations ...
//
// Retrieve Common Data ...
string symbol = eaSignallers[is].GetSymbol();
ENUM_TIMEFRAMES period = eaSignallers[is].GetPeriod();
//
// Required Value For SL/TP Calculations ...
double points = GetPoints(symbol);
double pip = GetPipPrice(symbol);
double pip2 = 2 * pip;
//
// Detect Signal Setups ...
has = eaSignallers[is].DetectSignalSetup(
r2r,
300 // Max Allowed SL Distance ...
);
if (has)
{
//
count = eaSignallers[is]
.AddConditionsIfNotExists();
//
eaSignallers[is].mConditions.Clean();
}
//
// Check Setuped Conditions Exists ...
count = ArraySize(eaSignallers[is].mConditionsCollection);
has = IsValidSize(count);
if (!has)
{
continue;
}
//
// Loop through Setuped Conditions for
// Validating or Looking up Triggers ...
for (int i = 0; i < count; i++)
{
//
// Check Signal Triggered or not ...
has = eaSignallers[is]
.DetectSignalTrigger(eaSignallers[is]
.mConditionsCollection[i]);
//
// If Triggered ...
if (has)
{
//
idx = i;
eaConditions = eaSignallers[is].mConditionsCollection[i];
break;
}
//
// Check Condition Validation ...
has = eaSignallers[is].mConditionsCollection[i].IsValid() &&
eaSignallers[is].mConditionsCollection[i].IsSetuped();
if (!has)
{
idx = i;
break;
}
}
//
// Remove Setuped Condition if provided IDX ...
has = IsValidIndex(idx);
if (has)
{
//
ArrayRemove(
eaSignallers[is].mConditionsCollection,
idx,
1 //
);
}
//
// Check EA Conditions is Valid or not ...
has = eaConditions.IsSetuped() &&
eaConditions.CanTrigger();
if (!has)
{
//
eaSignal.Clean();
eaConditions.Clean();
//
continue;
}
//
// Setting Time to Conditions ...
eaConditions.time = cTime;
has = ToPositionType(
type,
eaConditions.type //
);
if (!has)
{
//
eaSignal.Clean();
eaConditions.Clean();
//
continue;
}
//
// Checking Trigger Direction ...
hasLong = eaConditions.HasBullishSignal();
hasShort = eaConditions.HasBearishSignal();
has = hasLong ||
hasShort;
if (!has)
{
//
eaSignal.Clean();
eaConditions.Clean();
//
continue;
}
//
// Preparing Signal ...
eaSignal.mode = mode;
eaSignal.type = type;
eaSignal.entry = GetEntry(
eaConditions.symbol,
eaConditions.dir //
);
eaSignal.provider = provider;
eaSignal.sl = eaConditions.sl;
eaSignal.tp = eaConditions.tp;
eaSignal.volume = X_MIN_VOLUME;
eaSignal.time = eaConditions.time;
eaSignal.symbol = eaConditions.symbol;
eaSignal.period = eaConditions.period;
//
// Handling Targets ...
Copy(
eaConditions.targets,
eaSignal.targets //
);
//
// Validate Signal ...
has = eaSignal.IsValid();
if (!has)
{
//
eaSignal.Clean();
eaConditions.Clean();
//
continue;
}
//
// Handle Volume Management ...
double iVolume = eaVolume.CalculateVolume(eaSignal);
if (iVolume > X_MIN_VOLUME &&
iVolume != eaSignal.volume)
{
eaSignal.volume = iVolume;
}
//
// Execute Signal ...
has = eaTradeManager.Execute(
eaSignal,
eaConditions //
);
//
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 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()
{
//
// Preparing Tags ...
eaTag =
(IsValid(eaLogSuffix)
? eaLogSuffix + "_"
: "") +
ShortName;
//
// EA Alert ...
eaAlert = new XCAlert(
eaTag,
eaEnableAlerts,
eaLogAlerts,
eaTerminalAlerts,
eaMailAlerts,
eaPushAlerts //
);
//
// EA Trade ...
eaTrade = new XCTrade(
eaSlippage,
eaMagicNumber,
eaMaxAllowedSpread,
eaMaxAllowedPositions,
eaMaxAllowedDrawdownFactor //
);
eaTrade.AddOnStopLossEventHandler(OnStopLossTriggered);
eaTrade.AddOnTakeProfitEventHandler(OnTakeProfitTriggered);
eaTrade.AddOnForceClosePositionEventHandler(OnPositionForceClosed);
//
// 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 //
);
//
InitSymbolSessions();
//
}
/**
* Initial Symbols and Active Sessions of EA ...
*/
void InitSymbolSessions()
{
//
string symbols[];
string sessions[];
string iSymbol = NULL;
XCXCAEASignaller *iSignaller;
//
// Parse Symbols ...
int symbolsCount = 0;
bool isMultiSymbol = IsValid(eaSymbols);
if (isMultiSymbol)
{
//
symbolsCount = SplitContent(
symbols,
eaSymbols //
);
isMultiSymbol = IsValidSize(symbolsCount);
}
if (!isMultiSymbol)
{
//
Add(
_Symbol,
symbols //
);
//
symbolsCount = 1;
}
//
// Parse Sessions ...
int sessionsCount = 0;
bool hasSession = IsValid(eaSymbolSessions);
if (hasSession)
{
//
// Extract Per Symbol Sessions ...
sessionsCount = SplitContent(
sessions,
eaSymbolSessions,
"|" //
);
}
//
// Setting Up Symbols ...
bool has = false;
//
for (int i = 0; i < symbolsCount; i++)
{
//
iSymbol = symbols[i];
//
// EA Signaller ...
iSignaller = new XCXCAEASignaller(
iSymbol,
_Period,
eaAnalysisPeriod // Analysing Period ...
);
//
Add(
iSignaller,
eaSignallers //
);
//
ZeroMemory(iSignaller);
}
//
// Setting Up Sessions ...
if (hasSession)
{
//
for (int i = 0; i < symbolsCount; i++)
{
//
iSymbol = symbols[i];
//
if (i < sessionsCount)
{
//
// Extract Per Symbol Sessions ...
string iSymbolSessionsStr[];
int iSymbolSessionsCount = SplitContent(
iSymbolSessionsStr,
sessions[i],
"," //
);
//
has = IsValidSize(iSymbolSessionsCount);
if (has)
{
//
// Loop through Symbols Sessions ...
for (int j = 0; j < iSymbolSessionsCount; j++)
{
//
string iSessionDescriptorStr = ExtractString(iSymbolSessionsStr[j]);
has = IsValid(iSessionDescriptorStr);
if (has)
{
//
// Extract Session Descriptor Data ...
string parts[];
int partsCount = SplitContent(
parts,
iSessionDescriptorStr,
"_" //
);
has = IsValidSize(partsCount) && partsCount == 3;
if (has)
{
//
string iName = parts[0];
string iStart = parts[1];
string iEnd = parts[2];
has = IsValid(iName) &&
IsValid(iStart) &&
IsValid(iEnd);
if (has)
{
//
eaTradeManager
.SetTradeSession(
iSymbol,
iStart,
iEnd,
iName //
);
}
}
//
Clean(parts);
}
}
}
//
Clean(iSymbolSessionsStr);
}
}
}
//
Clean(symbols);
Clean(sessions);
ZeroMemory(iSignaller);
}
/**
* Handling Time Reporting ...
*/
void HandleTimeReport()
{
//
// 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);
}
}
//