//+------------------------------------------------------------------+ //| 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 #include //--- 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; }