735 lines
No EOL
28 KiB
MQL5
735 lines
No EOL
28 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| ERMT_6.9-DualDash.mq5|
|
|
//| Enterprise Risk Management Terminal v6.9 |
|
|
//| Institutional Grade Risk Management |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2024, Institutional Trading Systems"
|
|
#property link "https://example.com"
|
|
#property version "6.902" // MQL5 Market compatible format (xxx.yyy)
|
|
#property description "Enterprise Risk Management Terminal - Dual Dashboard Edition"
|
|
#property description "Professional risk management system with advanced position monitoring"
|
|
#property description "Features: Real-time risk metrics, multi-symbol monitoring, dual dashboard display"
|
|
|
|
// Optional: Keep human-readable version as a constant
|
|
#define VERSION_STRING "6.9 Dual Dashboard"
|
|
#define VERSION_MAJOR 6
|
|
#define VERSION_MINOR 9
|
|
#define VERSION_BUILD 0
|
|
//--- Include base MQL5 classes
|
|
#include <Object.mqh>
|
|
#include <Trade/Trade.mqh>
|
|
|
|
//--- Include system modules
|
|
#include "Modules/DataTypes.mqh"
|
|
#include "Modules/Utilities.mqh"
|
|
#include "Modules/RiskManager.mqh"
|
|
#include "Modules/TradeManager.mqh"
|
|
#include "Modules/TechnicalAnalysis.mqh"
|
|
#include "Modules/EntrySystem.mqh"
|
|
#include "Modules/Dashboard.mqh" // Original Dashboard
|
|
#include "Modules/Dashboard_SelfContained.mqh" // New Self-Contained Dashboard
|
|
#include "Modules/ExternalTradeManager.mqh"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| INPUT PARAMETERS - GROUPED BY MODULE |
|
|
//+------------------------------------------------------------------+
|
|
|
|
//--- System Configuration
|
|
input group "=== SYSTEM CONFIGURATION ==="
|
|
input bool SystemEnabled = true; // Enable System
|
|
input int TradingMagic = 12345; // EA Magic Number
|
|
input ENUM_LOG_LEVEL LogLevel = LOG_INFO; // Logging Level
|
|
|
|
//--- External Trade Management
|
|
input group "=== EXTERNAL TRADE MANAGEMENT ==="
|
|
input bool ManageExternalTrades = true; // Manage External Trades
|
|
input int MagicNumberFilter = 0; // External Magic Filter (0=all)
|
|
input bool ForceStopLoss = true; // Force SL on Unprotected Trades
|
|
input bool ForceTakeProfit = true; // Force TP on Unprotected Trades
|
|
input bool OverrideExternalSL = false; // Override Existing Stop Loss
|
|
input bool OverrideExternalTP = false; // Override Existing Take Profit
|
|
input double ExternalDefaultSL_ATR = 2.0; // Default SL (ATR Multiples)
|
|
input double ExternalDefaultTP_Ratio = 1.5; // Default TP/SL Ratio
|
|
input bool CloseExcessiveRisk = true; // Close Trades Exceeding Risk
|
|
input double MaxExternalRiskPercent = 5.0; // Max Risk % for External Trades
|
|
input bool RealTimeSync = true; // Real-time Trade Synchronization
|
|
input int SyncIntervalMS = 500; // Sync Check Interval (ms)
|
|
|
|
//--- Entry System Parameters
|
|
input group "=== ENTRY SYSTEM ==="
|
|
input ENUM_ENTRY_MODE EntryMode = ENTRY_MA_CROSS; // Entry System Type
|
|
input bool EnableMultipleEntries = false; // Allow Multiple Entries
|
|
input int MaxPositions = 3; // Maximum Positions
|
|
input double MinTimeBetweenTrades = 60; // Min Minutes Between Trades
|
|
|
|
//--- Risk Management
|
|
input group "=== RISK MANAGEMENT ==="
|
|
input ENUM_POSITION_SIZING SizingMode = SIZING_FIXED_PERCENT; // Position Sizing Method
|
|
input double FixedLotSize = 0.01; // Fixed Lot Size
|
|
input double RiskPercent = 1.0; // Risk Per Trade (%)
|
|
input double MaxRiskPercent = 2.0; // Maximum Risk Per Trade (%)
|
|
input double MaxDailyDrawdown = 5.0; // Max Daily Drawdown (%)
|
|
input double MaxTotalExposure = 10.0; // Max Total Exposure (%)
|
|
|
|
//--- Trade Management
|
|
input group "=== TRADE MANAGEMENT ==="
|
|
input ENUM_TP_MODE TPMode = TP_FIXED_RR; // Take Profit Mode
|
|
input ENUM_SL_MODE SLMode = SL_ATR; // Stop Loss Mode
|
|
input bool EnableBreakeven = true; // Enable Breakeven
|
|
input double BreakevenTrigger = 1.0; // Breakeven Trigger (R)
|
|
input bool EnableTrailing = true; // Enable Trailing Stop
|
|
input double TrailingStart = 1.5; // Trailing Start (R)
|
|
input bool EnablePartialClose = true; // Enable Partial Close
|
|
input int PartialLevels = 3; // Number of Partial Levels
|
|
|
|
//--- Technical Analysis
|
|
input group "=== TECHNICAL ANALYSIS ==="
|
|
input bool UseSupportResistance = true; // Use S/R Levels
|
|
input bool UseFibonacci = false; // Use Fibonacci Levels
|
|
input bool UsePivotPoints = true; // Use Pivot Points
|
|
input bool UseMarketStructure = true; // Analyze Market Structure
|
|
input int TechnicalLookback = 100; // Technical Lookback Period
|
|
|
|
//--- ORIGINAL Dashboard Parameters
|
|
input group "=== ORIGINAL DASHBOARD ==="
|
|
input bool ShowOriginalDashboard = true; // Show Original Dashboard
|
|
input int OriginalDashboardX = 20; // Original Dashboard X Position
|
|
input int OriginalDashboardY = 30; // Original Dashboard Y Position
|
|
input color DashboardColor = clrWhiteSmoke; // Dashboard Text Color
|
|
input color ProfitColor = clrLime; // Profit Color
|
|
input color LossColor = clrRed; // Loss Color
|
|
input int UpdateFrequency = 1; // Update Frequency (seconds)
|
|
|
|
//--- NEW Self-Contained Dashboard Parameters
|
|
input group "=== NEW SELF-CONTAINED DASHBOARD ==="
|
|
input bool ShowNewDashboard = true; // Show New Dashboard
|
|
input int NewDashboardX = 350; // New Dashboard X Position (offset to right)
|
|
input int NewDashboardY = 30; // New Dashboard Y Position
|
|
input int NewDashboardTheme = 0; // Theme (0=Dark, 1=Light, 2=Contrast, 3=Matrix, 4=Ocean, 5=Auto)
|
|
input bool NewDashboardCompact = false; // Start in Compact Mode
|
|
|
|
//--- Reporting Options
|
|
input group "=== REPORTING OPTIONS ==="
|
|
input bool SaveTradeLog = true; // Save Trade Log
|
|
input bool SendAlerts = true; // Send Alert Notifications
|
|
input bool GenerateReports = true; // Generate Periodic Reports
|
|
input bool ExportCSV = true; // Export Reports to CSV
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| GLOBAL VARIABLES & OBJECTS |
|
|
//+------------------------------------------------------------------+
|
|
|
|
//--- Module instances
|
|
CRiskManager *RiskMgr;
|
|
CTradeManager *TradeMgr;
|
|
CTechnicalAnalysis *TechAnalysis;
|
|
CEntrySystem *EntrySystem;
|
|
CDashboard *OriginalDashboard; // Original Dashboard
|
|
CDashboardSC *NewDashboard; // New Self-Contained Dashboard
|
|
CExternalTradeManager *ExtTradeMgr;
|
|
|
|
//--- Trade tracking
|
|
ManagedTrade g_ManagedTrades[];
|
|
int g_TotalTrades;
|
|
|
|
//--- Performance tracking
|
|
PerformanceMetrics g_Performance;
|
|
RiskMetrics g_RiskMetrics;
|
|
MarketConditions g_MarketConditions;
|
|
|
|
//--- Timing control
|
|
datetime g_LastUpdateTime;
|
|
datetime g_LastEntryCheck;
|
|
datetime g_LastReportTime;
|
|
ulong g_LastSyncTime;
|
|
|
|
//--- Status flags
|
|
bool g_IsInitialized = false;
|
|
bool g_InPosition = false;
|
|
int g_ConsecutiveLosses = 0;
|
|
|
|
|
|
bool ShowOriginalDashboard = true; // Show original dashboard flag
|
|
bool ShowNewDashboard = true; // Show new dashboard flag
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
Print("=== ERMT 6.8 Initializing with Dual Dashboard Support ===");
|
|
|
|
//--- Initialize modules
|
|
RiskMgr = new CRiskManager();
|
|
if(!RiskMgr.Initialize(RiskPercent, MaxRiskPercent, MaxDailyDrawdown, MaxTotalExposure))
|
|
{
|
|
Print("Failed to initialize Risk Manager");
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
TradeMgr = new CTradeManager();
|
|
if(!TradeMgr.Initialize(TPMode, SLMode, EnableBreakeven, EnableTrailing, EnablePartialClose))
|
|
{
|
|
Print("Failed to initialize Trade Manager");
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
TechAnalysis = new CTechnicalAnalysis();
|
|
if(!TechAnalysis.Initialize(TechnicalLookback, UseSupportResistance,
|
|
UseFibonacci, UsePivotPoints, UseMarketStructure))
|
|
{
|
|
Print("Failed to initialize Technical Analysis");
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
EntrySystem = new CEntrySystem();
|
|
if(!EntrySystem.Initialize(EntryMode, EnableMultipleEntries, MaxPositions))
|
|
{
|
|
Print("Failed to initialize Entry System");
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
//--- Initialize External Trade Manager if enabled
|
|
if(ManageExternalTrades)
|
|
{
|
|
ExtTradeMgr = new CExternalTradeManager();
|
|
if(!ExtTradeMgr.Initialize(MagicNumberFilter, ForceStopLoss, ForceTakeProfit,
|
|
OverrideExternalSL, OverrideExternalTP))
|
|
{
|
|
Print("Failed to initialize External Trade Manager");
|
|
return INIT_FAILED;
|
|
}
|
|
Print("External Trade Manager initialized successfully");
|
|
}
|
|
|
|
//--- Initialize ORIGINAL Dashboard
|
|
if(ShowOriginalDashboard)
|
|
{
|
|
OriginalDashboard = new CDashboard();
|
|
if(!OriginalDashboard.Create(OriginalDashboardX, OriginalDashboardY,
|
|
DashboardColor, ProfitColor, LossColor))
|
|
{
|
|
Print("Failed to create Original Dashboard");
|
|
// Non-critical, continue
|
|
}
|
|
else
|
|
{
|
|
Print("Original Dashboard created at position (", OriginalDashboardX, ",", OriginalDashboardY, ")");
|
|
}
|
|
}
|
|
|
|
//--- Initialize NEW Self-Contained Dashboard
|
|
if(ShowNewDashboard)
|
|
{
|
|
NewDashboard = new CDashboardSC();
|
|
if(!NewDashboard.Create(NewDashboardX, NewDashboardY,
|
|
(ENUM_DASH_THEME)NewDashboardTheme, NewDashboardCompact))
|
|
{
|
|
Print("Failed to create New Self-Contained Dashboard");
|
|
// Non-critical, continue
|
|
}
|
|
else
|
|
{
|
|
Print("New Self-Contained Dashboard created at position (", NewDashboardX, ",", NewDashboardY, ")");
|
|
Print("Theme: ", NewDashboardTheme, ", Compact: ", NewDashboardCompact);
|
|
}
|
|
}
|
|
|
|
//--- Initialize performance tracking
|
|
InitializePerformanceMetrics();
|
|
|
|
//--- Set timer for updates
|
|
EventSetMillisecondTimer(UpdateFrequency * 1000);
|
|
|
|
g_IsInitialized = true;
|
|
g_LastUpdateTime = TimeCurrent();
|
|
g_LastSyncTime = GetMicrosecondCount();
|
|
|
|
Print("=== ERMT 6.8 Initialization Complete ===");
|
|
Print("Original Dashboard: ", ShowOriginalDashboard ? "ENABLED" : "DISABLED");
|
|
Print("New Dashboard: ", ShowNewDashboard ? "ENABLED" : "DISABLED");
|
|
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
Print("=== ERMT 6.8 Shutting Down ===");
|
|
|
|
EventKillTimer();
|
|
|
|
//--- Clean up BOTH dashboards
|
|
if(OriginalDashboard != NULL)
|
|
{
|
|
OriginalDashboard.Destroy();
|
|
delete OriginalDashboard;
|
|
OriginalDashboard = NULL;
|
|
Print("Original Dashboard destroyed");
|
|
}
|
|
|
|
if(NewDashboard != NULL)
|
|
{
|
|
NewDashboard.Destroy();
|
|
delete NewDashboard;
|
|
NewDashboard = NULL;
|
|
Print("New Dashboard destroyed");
|
|
}
|
|
|
|
//--- Clean up modules
|
|
if(RiskMgr != NULL) delete RiskMgr;
|
|
if(TradeMgr != NULL) delete TradeMgr;
|
|
if(TechAnalysis != NULL) delete TechAnalysis;
|
|
if(EntrySystem != NULL) delete EntrySystem;
|
|
if(ExtTradeMgr != NULL) delete ExtTradeMgr;
|
|
|
|
Print("=== ERMT 6.8 Shutdown Complete ===");
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
if(!SystemEnabled || !g_IsInitialized) return;
|
|
|
|
//--- Update market conditions
|
|
g_MarketConditions = TechAnalysis.AnalyzeMarket();
|
|
|
|
//--- Manage external trades with real-time sync
|
|
if(ManageExternalTrades && ExtTradeMgr != NULL)
|
|
{
|
|
if(RealTimeSync)
|
|
{
|
|
ulong current_time = GetMicrosecondCount();
|
|
if(current_time - g_LastSyncTime >= (ulong)(SyncIntervalMS * 1000))
|
|
{
|
|
ProcessExternalTrades();
|
|
g_LastSyncTime = current_time;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ProcessExternalTrades();
|
|
}
|
|
}
|
|
|
|
//--- Update managed trades
|
|
UpdateManagedTrades();
|
|
|
|
//--- Check for new entry signals
|
|
if(!g_InPosition || EnableMultipleEntries)
|
|
{
|
|
CheckEntrySignals();
|
|
}
|
|
|
|
//--- Update risk metrics
|
|
g_RiskMetrics = RiskMgr.CalculateCurrentRisk(g_ManagedTrades);
|
|
|
|
//--- Check risk limits
|
|
if(RiskMgr.IsRiskLimitExceeded(g_RiskMetrics))
|
|
{
|
|
HandleRiskLimitBreach();
|
|
}
|
|
|
|
//--- Update performance metrics
|
|
UpdatePerformanceMetrics();
|
|
|
|
//--- Update BOTH dashboards
|
|
if(TimeCurrent() - g_LastUpdateTime >= UpdateFrequency)
|
|
{
|
|
UpdateDashboards();
|
|
g_LastUpdateTime = TimeCurrent();
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Timer function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTimer()
|
|
{
|
|
//--- Periodic dashboard updates
|
|
UpdateDashboards();
|
|
|
|
//--- Generate reports if enabled
|
|
if(GenerateReports && TimeCurrent() - g_LastReportTime >= 3600) // Hourly
|
|
{
|
|
GeneratePerformanceReport();
|
|
g_LastReportTime = TimeCurrent();
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Update BOTH dashboards |
|
|
//+------------------------------------------------------------------+
|
|
void UpdateDashboards()
|
|
{
|
|
//--- Prepare data for dashboards
|
|
CollectPerformanceMetrics(g_Performance);
|
|
CalculateRiskMetrics(g_RiskMetrics);
|
|
|
|
//--- Update Original Dashboard
|
|
if(ShowOriginalDashboard && OriginalDashboard != NULL)
|
|
{
|
|
OriginalDashboard.Update(g_Performance, g_ManagedTrades, g_MarketConditions);
|
|
}
|
|
|
|
//--- Update New Self-Contained Dashboard
|
|
if(ShowNewDashboard && NewDashboard != NULL)
|
|
{
|
|
NewDashboard.Update(g_Performance, g_RiskMetrics, g_MarketConditions);
|
|
}
|
|
|
|
//--- Optional: Log comparison for testing
|
|
if(LogLevel >= LOG_DEBUG)
|
|
{
|
|
Print("Dashboard Update - Balance: ", g_Performance.current_balance,
|
|
", Equity: ", g_Performance.current_equity,
|
|
", Exposure: ", g_RiskMetrics.current_exposure, "%",
|
|
", Market: ", EnumToString(g_MarketConditions.condition));
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Process external trades |
|
|
//+------------------------------------------------------------------+
|
|
void ProcessExternalTrades()
|
|
{
|
|
if(ExtTradeMgr == NULL) return;
|
|
|
|
//--- Scan for external trades
|
|
int external_trades = ExtTradeMgr.ScanExternalTrades();
|
|
|
|
if(external_trades > 0)
|
|
{
|
|
//--- Process each external trade
|
|
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
|
{
|
|
if(PositionSelectByIndex(i))
|
|
{
|
|
// Skip our own trades
|
|
if(PositionGetInteger(POSITION_MAGIC) == TradingMagic) continue;
|
|
|
|
// Apply management rules
|
|
ExtTradeMgr.ManageExternalTrade(PositionGetInteger(POSITION_TICKET));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Update managed trades |
|
|
//+------------------------------------------------------------------+
|
|
void UpdateManagedTrades()
|
|
{
|
|
g_TotalTrades = 0;
|
|
ArrayResize(g_ManagedTrades, 0);
|
|
|
|
//--- Scan all positions
|
|
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
|
{
|
|
if(PositionSelectByIndex(i))
|
|
{
|
|
ManagedTrade trade;
|
|
trade.ticket = PositionGetInteger(POSITION_TICKET);
|
|
trade.symbol = PositionGetString(POSITION_SYMBOL);
|
|
trade.type = (ENUM_ORDER_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
trade.volume = PositionGetDouble(POSITION_VOLUME);
|
|
trade.open_price = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
trade.sl = PositionGetDouble(POSITION_SL);
|
|
trade.tp = PositionGetDouble(POSITION_TP);
|
|
trade.current_profit = PositionGetDouble(POSITION_PROFIT);
|
|
trade.open_time = (datetime)PositionGetInteger(POSITION_TIME);
|
|
trade.magic = PositionGetInteger(POSITION_MAGIC);
|
|
trade.is_external = (trade.magic != TradingMagic);
|
|
|
|
//--- Calculate risk metrics
|
|
if(trade.sl > 0)
|
|
{
|
|
double risk_points = MathAbs(trade.open_price - trade.sl);
|
|
trade.risk_amount = risk_points * trade.volume *
|
|
SymbolInfoDouble(trade.symbol, SYMBOL_TRADE_TICK_VALUE);
|
|
}
|
|
|
|
//--- Add to managed trades array
|
|
ArrayResize(g_ManagedTrades, g_TotalTrades + 1);
|
|
g_ManagedTrades[g_TotalTrades] = trade;
|
|
g_TotalTrades++;
|
|
|
|
//--- Apply trade management
|
|
if(!trade.is_external)
|
|
{
|
|
TradeMgr.ManageTrade(trade, g_MarketConditions);
|
|
}
|
|
}
|
|
}
|
|
|
|
g_InPosition = (g_TotalTrades > 0);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Check for entry signals |
|
|
//+------------------------------------------------------------------+
|
|
void CheckEntrySignals()
|
|
{
|
|
//--- Rate limiting
|
|
if(TimeCurrent() - g_LastEntryCheck < MinTimeBetweenTrades * 60) return;
|
|
|
|
//--- Get entry signal
|
|
EntrySignal signal = EntrySystem.CheckForEntry(g_MarketConditions);
|
|
|
|
if(signal.signal_type != SIGNAL_NONE)
|
|
{
|
|
//--- Calculate position size
|
|
double lot_size = RiskMgr.CalculatePositionSize(
|
|
signal.entry_price,
|
|
signal.stop_loss,
|
|
RiskPercent
|
|
);
|
|
|
|
//--- Validate lot size
|
|
if(lot_size > 0 && RiskMgr.ValidateNewPosition(lot_size, g_RiskMetrics))
|
|
{
|
|
//--- Execute trade
|
|
CTrade trade;
|
|
trade.SetExpertMagicNumber(TradingMagic);
|
|
|
|
bool result = false;
|
|
if(signal.signal_type == SIGNAL_BUY)
|
|
{
|
|
result = trade.Buy(lot_size, _Symbol, signal.entry_price,
|
|
signal.stop_loss, signal.take_profit,
|
|
"ERMT 6.8 Buy");
|
|
}
|
|
else if(signal.signal_type == SIGNAL_SELL)
|
|
{
|
|
result = trade.Sell(lot_size, _Symbol, signal.entry_price,
|
|
signal.stop_loss, signal.take_profit,
|
|
"ERMT 6.8 Sell");
|
|
}
|
|
|
|
if(result)
|
|
{
|
|
g_LastEntryCheck = TimeCurrent();
|
|
Print("Trade executed: ", EnumToString(signal.signal_type),
|
|
" Lot: ", lot_size, " SL: ", signal.stop_loss,
|
|
" TP: ", signal.take_profit);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Handle risk limit breach |
|
|
//+------------------------------------------------------------------+
|
|
void HandleRiskLimitBreach()
|
|
{
|
|
Print("WARNING: Risk limit breached! Exposure: ", g_RiskMetrics.current_exposure, "%");
|
|
|
|
if(CloseExcessiveRisk)
|
|
{
|
|
//--- Close highest risk positions first
|
|
for(int i = 0; i < g_TotalTrades; i++)
|
|
{
|
|
if(g_ManagedTrades[i].risk_amount > MaxExternalRiskPercent)
|
|
{
|
|
CTrade trade;
|
|
trade.PositionClose(g_ManagedTrades[i].ticket);
|
|
Print("Closed excessive risk position: ", g_ManagedTrades[i].ticket);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(SendAlerts)
|
|
{
|
|
Alert("ERMT 6.8: Risk limit exceeded! Current exposure: ",
|
|
DoubleToString(g_RiskMetrics.current_exposure, 2), "%");
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Initialize performance metrics |
|
|
//+------------------------------------------------------------------+
|
|
void InitializePerformanceMetrics()
|
|
{
|
|
g_Performance.starting_balance = AccountInfoDouble(ACCOUNT_BALANCE);
|
|
g_Performance.current_balance = g_Performance.starting_balance;
|
|
g_Performance.current_equity = AccountInfoDouble(ACCOUNT_EQUITY);
|
|
g_Performance.peak_balance = g_Performance.starting_balance;
|
|
g_Performance.total_trades = 0;
|
|
g_Performance.winning_trades = 0;
|
|
g_Performance.losing_trades = 0;
|
|
g_Performance.total_profit = 0;
|
|
g_Performance.total_loss = 0;
|
|
g_Performance.largest_win = 0;
|
|
g_Performance.largest_loss = 0;
|
|
g_Performance.consecutive_wins = 0;
|
|
g_Performance.consecutive_losses = 0;
|
|
g_Performance.max_drawdown = 0;
|
|
g_Performance.current_drawdown = 0;
|
|
g_Performance.daily_profit = 0;
|
|
g_Performance.weekly_profit = 0;
|
|
g_Performance.monthly_profit = 0;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Update performance metrics |
|
|
//+------------------------------------------------------------------+
|
|
void UpdatePerformanceMetrics()
|
|
{
|
|
g_Performance.current_balance = AccountInfoDouble(ACCOUNT_BALANCE);
|
|
g_Performance.current_equity = AccountInfoDouble(ACCOUNT_EQUITY);
|
|
|
|
//--- Update peak and drawdown
|
|
if(g_Performance.current_balance > g_Performance.peak_balance)
|
|
{
|
|
g_Performance.peak_balance = g_Performance.current_balance;
|
|
}
|
|
|
|
double drawdown = (g_Performance.peak_balance - g_Performance.current_balance) /
|
|
g_Performance.peak_balance * 100;
|
|
g_Performance.current_drawdown = drawdown;
|
|
|
|
if(drawdown > g_Performance.max_drawdown)
|
|
{
|
|
g_Performance.max_drawdown = drawdown;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Collect performance metrics |
|
|
//+------------------------------------------------------------------+
|
|
void CollectPerformanceMetrics(PerformanceMetrics &perf)
|
|
{
|
|
perf = g_Performance; // Copy current metrics
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Calculate risk metrics |
|
|
//+------------------------------------------------------------------+
|
|
void CalculateRiskMetrics(RiskMetrics &risk)
|
|
{
|
|
risk = g_RiskMetrics; // Copy current metrics
|
|
|
|
//--- Additional calculations if needed
|
|
risk.max_daily_drawdown = MaxDailyDrawdown;
|
|
risk.max_total_exposure = MaxTotalExposure;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Generate performance report |
|
|
//+------------------------------------------------------------------+
|
|
void GeneratePerformanceReport()
|
|
{
|
|
if(!GenerateReports) return;
|
|
|
|
string report = "=== ERMT 6.8 Performance Report ===\n";
|
|
report += "Time: " + TimeToString(TimeCurrent()) + "\n";
|
|
report += "Balance: $" + DoubleToString(g_Performance.current_balance, 2) + "\n";
|
|
report += "Equity: $" + DoubleToString(g_Performance.current_equity, 2) + "\n";
|
|
report += "Drawdown: " + DoubleToString(g_Performance.current_drawdown, 2) + "%\n";
|
|
report += "Total Trades: " + IntegerToString(g_Performance.total_trades) + "\n";
|
|
report += "Win Rate: " + DoubleToString(g_Performance.winning_trades * 100.0 /
|
|
MathMax(1, g_Performance.total_trades), 1) + "%\n";
|
|
report += "Current Exposure: " + DoubleToString(g_RiskMetrics.current_exposure, 2) + "%\n";
|
|
report += "Market Condition: " + EnumToString(g_MarketConditions.condition) + "\n";
|
|
|
|
Print(report);
|
|
|
|
if(SaveTradeLog)
|
|
{
|
|
SaveReportToFile(report);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Save report to file |
|
|
//+------------------------------------------------------------------+
|
|
void SaveReportToFile(string report)
|
|
{
|
|
string filename = "ERMT_Report_" + TimeToString(TimeCurrent(), TIME_DATE) + ".txt";
|
|
int handle = FileOpen(filename, FILE_WRITE | FILE_TXT);
|
|
|
|
if(handle != INVALID_HANDLE)
|
|
{
|
|
FileWrite(handle, report);
|
|
FileClose(handle);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Chart event handler for dashboard interaction |
|
|
//+------------------------------------------------------------------+
|
|
void OnChartEvent(const int id, const long &lparam,
|
|
const double &dparam, const string &sparam)
|
|
{
|
|
if(id == CHARTEVENT_KEYDOWN)
|
|
{
|
|
switch((int)lparam)
|
|
{
|
|
//--- Toggle Original Dashboard
|
|
case 'O':
|
|
ShowOriginalDashboard = !ShowOriginalDashboard;
|
|
if(ShowOriginalDashboard && OriginalDashboard != NULL)
|
|
OriginalDashboard.Show();
|
|
else if(OriginalDashboard != NULL)
|
|
OriginalDashboard.Hide();
|
|
Comment("Original Dashboard: ", ShowOriginalDashboard ? "ON" : "OFF");
|
|
break;
|
|
|
|
//--- Toggle New Dashboard
|
|
case 'N':
|
|
ShowNewDashboard = !ShowNewDashboard;
|
|
if(ShowNewDashboard && NewDashboard != NULL)
|
|
NewDashboard.SetVisible(ShowNewDashboard);
|
|
Comment("New Dashboard: ", ShowNewDashboard ? "ON" : "OFF");
|
|
break;
|
|
|
|
//--- Cycle themes on New Dashboard
|
|
case 'T':
|
|
if(NewDashboard != NULL)
|
|
{
|
|
int current_theme = (int)NewDashboard.GetTheme();
|
|
current_theme = (current_theme + 1) % 6;
|
|
NewDashboard.SetTheme((ENUM_DASH_THEME)current_theme);
|
|
Comment("Theme changed to: ", current_theme);
|
|
}
|
|
break;
|
|
|
|
//--- Toggle compact mode on New Dashboard
|
|
case 'C':
|
|
if(NewDashboard != NULL)
|
|
{
|
|
NewDashboard.ToggleCompact();
|
|
Comment("Compact mode toggled");
|
|
}
|
|
break;
|
|
|
|
//--- Show comparison
|
|
case 'D':
|
|
Comment("Dashboards Comparison:\n",
|
|
"Original: ", ShowOriginalDashboard ? "ON" : "OFF", " at (", OriginalDashboardX, ",", OriginalDashboardY, ")\n",
|
|
"New: ", ShowNewDashboard ? "ON" : "OFF", " at (", NewDashboardX, ",", NewDashboardY, ")\n",
|
|
"Balance: $", DoubleToString(g_Performance.current_balance, 2), "\n",
|
|
"Equity: $", DoubleToString(g_Performance.current_equity, 2), "\n",
|
|
"Exposure: ", DoubleToString(g_RiskMetrics.current_exposure, 2), "%\n",
|
|
"Market: ", EnumToString(g_MarketConditions.condition));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Tester function for optimization |
|
|
//+------------------------------------------------------------------+
|
|
double OnTester()
|
|
{
|
|
//--- Return profit factor for optimization
|
|
if(g_Performance.total_loss > 0)
|
|
return g_Performance.total_profit / g_Performance.total_loss;
|
|
else
|
|
return g_Performance.total_profit;
|
|
} |