//+------------------------------------------------------------------+ //| ERMT_PME.mq5 v1.0 | //| Enhanced Risk Management Tool - PME | //| Pure Management Edition - No Entry, Exit Only | //+------------------------------------------------------------------+ #property copyright "ERMT PME v1.0 - Pure Management Edition" #property link "https://github.com/ERMT" #property version "1.00" #property description "Professional position management overlay - Manages ALL positions" #property strict // Include modules #include "Modules_PME/DataTypes_PME.mqh" #include "Modules_PME/Utilities_PME.mqh" #include "Modules_PME/RiskManager_PME.mqh" //Original - may work with Galileo FX //#include "Modules_PME/TechnicalAnalysis_PME.mqh" //#include "Modules_PME/PositionManager_PME.mqh" // Fix for premature exits #include "Modules_PME/TechnicalAnalysis_PME_Optimised.mqh" #include "Modules_PME/PositionManager_PME_Complete.mqh" #include "Modules/ProfitMaximizer_PME.mqh" ////+------------------------------------------------------------------+ ////| Input Parameters | ////+------------------------------------------------------------------+ // //+------------------------------------------------------------------+ //| PROFIT MAXIMIZATION CONFIGURATION | //+------------------------------------------------------------------+ // === ENHANCED PROFIT SETTINGS (Replace old ones) ===// bool InpManageAllPositions = true; // Manage all positions int InpMagicFilter = 0; // 0 = manage all trades ENUM_MANAGEMENT_MODE InpDefaultMode = MODE_BREAKEVEN_TRAIL; // Conservative start ENUM_MANAGEMENT_LEVEL InpStartLevel = LEVEL_STANDARD; // Standard management input group "💰 Profit Maximization Settings" // === RISK PROTECTION (Wider Tolerances) === double InpMaxLossPerTrade = 3.0; // Increased from 2.0% double InpMaxDailyLoss = 12.0; // Increased from 6.0% double InpMaxDrawdown = 30.0; // Increased from 20.0% double InpMaxCorrelation = 0.85; // Increased correlation tolerance // === EMERGENCY PROTECTION (Wider Stops) === bool InpApplyEmergencyStops = true; // Keep protection active double InpEmergencySLMultiplier = 3.0; // Increased from 2.0 ATR double InpEmergencyTPMultiplier = 5.0; // Increased from 3.0 ATR // === DYNAMIC STOP MANAGEMENT === bool InpDynamicStops = true; // Enable dynamic adjustments bool InpTightenOnProfit = true; // Tighten stops as profit grows double InpTightenThreshold = 75; // Only tighten after 75 points profit bool InpProtectProfits = true; // Protect accumulated profits double InpProtectionThreshold = 100; // Start protecting after 100 points // === BREAKEVEN CONFIGURATION (Delayed) === bool InpBreakevenEnabled = true; // Enable breakeven double InpBreakevenTrigger = 40; // Increased from 20 points double InpBreakevenOffset = 8; // Increased from 2 points bool InpMultiLevelBE = true; // Enable multi-level breakeven // Multi-Level Breakeven Thresholds double InpBE_Level1_Trigger = 40; // First BE level double InpBE_Level1_Offset = 8; double InpBE_Level2_Trigger = 80; // Second BE level double InpBE_Level2_Offset = 20; double InpBE_Level3_Trigger = 150; // Third BE level double InpBE_Level3_Offset = 50; // === TRAILING STOP CONFIGURATION (Wider) === ENUM_TRAILING_METHOD InpTrailingMethod = TRAIL_ATR; // ATR-based for volatility adaptation double InpTrailStart = 60; // Start trailing after 60 points double InpTrailDistance = 40; // Increased from 20 points double InpTrailStep = 15; // Minimum step for trail adjustment bool InpAdaptiveTrailing = true; // Adapt to market conditions // Volatility-Based Trail Adjustments double InpLowVolatilityMultiplier = 0.8; // Tighter trail in quiet markets double InpHighVolatilityMultiplier = 1.5; // Wider trail in volatile markets double InpVolatilityThreshold = 1.2; // ATR threshold for high volatility // === PARTIAL CLOSE STRATEGY (Optimized) === bool InpPartialEnabled = true; // Enable partial closing int InpPartialLevels = 4; // Use 4 partial levels // Progressive Partial Close Levels double InpPartialTrigger1 = 50; // First partial at 50 points double InpPartialPercent1 = 20; // Only close 20% (keep 80% running) double InpPartialTrigger2 = 100; // Second partial at 100 points double InpPartialPercent2 = 20; // Close another 20% (60% remaining) double InpPartialTrigger3 = 200; // Third partial at 200 points double InpPartialPercent3 = 25; // Close 25% (35% remaining) double InpPartialTrigger4 = 400; // Fourth partial at 400 points double InpPartialPercent4 = 20; // Close 20% (15% for runner) // Runner Configuration input double InpRunnerPercentage = 15; // Runner Size (% to keep) input double InpRunnerTrailMultiplier = 2.0; // Runner Trail Multiplier input double InpRunnerExitThreshold = 500; // Runner Exit (points) // === EXIT MANAGEMENT (Disabled Aggressive Exits) === bool InpUseTechnicalExits = false; // DISABLED - prevent premature exits bool InpTimeBasedExits = false; // DISABLED - no time limits int InpMaxBarsInTrade = 1000; // Increased from 100 if enabled bool InpReduceRiskOverTime = false; // DISABLED - maintain position size // === PROFIT PROTECTION MECHANISM === bool InpProtectProfitEnabled = true; // Enable profit protection double InpProfitProtectionStart = 100; // Start protecting after 100 points double InpMaxRetracement = 60; // Allow 60% retracement from peak double InpLockInProfit = 40; // Lock in 40% of peak profit minimum // === TIME FILTERS (Relaxed) === bool InpUseTimeFilter = false; // Disable time restrictions int InpStartHour = 0; // Trade 24 hours if enabled int InpEndHour = 24; bool InpFridayClose = false; // DISABLED - no Friday close int InpFridayCloseHour = 23; // Latest possible if enabled // === SESSION-BASED ADJUSTMENTS === bool InpSessionBasedManagement = true; // Adjust by trading session // Asian Session (Conservative) double InpAsianTrailMultiplier = 1.2; // Wider trails double InpAsianPartialMultiplier = 1.5; // Delay partials // London Session (Standard) double InpLondonTrailMultiplier = 1.0; // Normal settings double InpLondonPartialMultiplier = 1.0; // New York Session (Aggressive) double InpNewYorkTrailMultiplier = 0.9; // Tighter trails double InpNewYorkPartialMultiplier = 0.8; // Earlier partials // === ADVANCED PROFIT MAXIMIZATION === bool InpUseVolumeAnalysis = true; // Consider volume in decisions double InpHighVolumeThreshold = 1.5; // 150% of average volume bool InpExtendTargetsOnMomentum = true; // Extend TP on strong momentum double InpMomentumThreshold = 2.0; // ATR multiplier for momentum // === SMART EXIT FILTERS === bool InpUseSmartExits = true; // Enable intelligent exit logic double InpMinProfitForExit = 30; // Minimum profit before any exit bool InpCheckSupportResistance = true; // Check S/R before exiting double InpSRBuffer = 10; // Points buffer from S/R levels // === SYSTEM SETTINGS === ENUM_LOG_LEVEL InpLogLevel = LOG_INFO; // Logging detail level bool InpSaveReports = true; // Save performance reports bool InpEmailAlerts = false; // Email notifications bool InpPushAlerts = false; // Push notifications bool InpSoundAlerts = true; /* // Management Control input group "=== Management Control ===" input string InpInstanceID = "PME1"; // Unique Instance ID input bool InpManageAllPositions = true; // Manage ALL positions input int InpMagicFilter = 0; // Filter by Magic (0=all) input ENUM_MANAGEMENT_MODE InpDefaultMode = MODE_BREAKEVEN_TRAIL; // Default Mode input ENUM_MANAGEMENT_LEVEL InpStartLevel = LEVEL_STANDARD; // Starting Level // Risk Protection input group "=== Risk Protection ===" input double InpMaxLossPerTrade = 3.0; // Max Loss Per Trade (%) input double InpMaxDailyLoss = 10.0; // Max Daily Loss (%) input double InpMaxDrawdown = 25.0; // Max Drawdown (%) input double InpMaxCorrelation = 0.8; // Max Correlation // Emergency Stops input group "=== Emergency Protection ===" input bool InpApplyEmergencyStops = true; // Apply Emergency Stops input double InpEmergencySLMultiplier = 2.5; // Emergency SL (ATR) input double InpEmergencyTPMultiplier = 4.0; // Emergency TP (ATR) // Stop Management input group "=== Stop Loss Management ===" input bool InpDynamicStops = true; // Dynamic Stop Adjustment input bool InpTightenOnProfit = true; // Tighten Stops on Profit input double InpTightenThreshold = 50; // Tighten Threshold (points) input bool InpProtectProfits = true; // Protect Profits // Breakeven input group "=== Breakeven Settings ===" input bool InpBreakevenEnabled = true; // Enable Breakeven input double InpBreakevenTrigger = 30; // BE Trigger (points) input double InpBreakevenOffset = 5; // BE Offset (points) input bool InpMultiLevelBE = false; // Multi-Level Breakeven // Trailing Stop input group "=== Trailing Stop ===" input ENUM_TRAILING_METHOD InpTrailingMethod = TRAIL_ATR; // Trailing Method input double InpTrailStart = 50; // Trail Start (points) input double InpTrailDistance = 30; // Trail Distance input double InpTrailStep = 10; // Trail Step input bool InpAdaptiveTrailing = true; // Adaptive Trailing // Partial Close input group "=== Partial Close ===" input bool InpPartialEnabled = true; // Enable Partial Close input double InpPartialTrigger1 = 50; // First Trigger (points) input double InpPartialPercent1 = 30; // First Close (%) input double InpPartialTrigger2 = 100; // Second Trigger (points) input double InpPartialPercent2 = 25; // Second Close (%) // Exit Management input group "=== Exit Management ===" input bool InpUseTechnicalExits = true; // Technical Exit Signals input bool InpTimeBasedExits = false; // Time-Based Exits input int InpMaxBarsInTrade = 500; // Max Bars in Trade input bool InpReduceRiskOverTime = false; // Reduce Risk Over Time // Time Filters input group "=== Time Filters ===" input bool InpUseTimeFilter = false; // Use Time Filter input int InpStartHour = 8; // Start Hour input int InpEndHour = 20; // End Hour input bool InpFridayClose = true; // Friday Close input int InpFridayCloseHour = 21; // Friday Close Hour // Display input group "=== Display Settings ===" input bool InpShowDashboard = true; // Show Dashboard input int InpDashboardX = 20; // Dashboard X input int InpDashboardY = 50; // Dashboard Y input int InpUpdateFrequency = 2; // Update Frequency (sec) // System input group "=== System Settings ===" input ENUM_LOG_LEVEL InpLogLevel = LOG_INFO; // Log Level input bool InpSaveReports = true; // Save Reports input bool InpEmailAlerts = false; // Email Alerts input bool InpPushAlerts = false; // Push Notifications input bool InpSoundAlerts = true; // Sound Alerts */ //+------------------------------------------------------------------+ //| Global Variables | //+------------------------------------------------------------------+ // Core components CUtilities* g_utils = NULL; CRiskManager* g_risk = NULL; CTechnicalAnalysis* g_tech = NULL; CPositionManager* g_manager = NULL; ProfitMaximizer* g_profit_max = NULL; // State tracking bool g_initialized = false; datetime g_last_update = 0; datetime g_session_start = 0; double g_session_start_balance = 0; double g_session_start_equity = 0; // Performance tracking int g_positions_detected = 0; int g_positions_managed = 0; int g_positions_closed = 0; double g_total_prevented = 0; double g_total_captured = 0; // Alert management datetime g_last_alert = 0; int g_alert_count = 0; // Dashboard elements (simplified) string g_dashboard_prefix = "PME_" + InpInstanceID + "-"; int g_dashboard_objects = 0; // Performance tracking struct PerformanceTracker { int trades_managed; double total_profit_captured; double total_loss_prevented; int runners_created; int extreme_profits; datetime last_update; }; PerformanceTracker g_performance;_tracker; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { Print("=================================================="); Print(" ERMT PME v1.0 - Pure Management Edition"); Print("=================================================="); Print("Initializing management system..."); // Validate inputs if(!ValidateInputs()) { Print("ERROR: Invalid input parameters"); return INIT_PARAMETERS_INCORRECT; } // Create core components g_utils = new CUtilities(); if(g_utils == NULL) { Print("ERROR: Failed to create Utilities"); return INIT_FAILED; } g_risk = new CRiskManager(); if(g_risk == NULL) { Print("ERROR: Failed to create RiskManager"); Cleanup(); return INIT_FAILED; } g_tech = new CTechnicalAnalysis(); if(g_tech == NULL) { Print("ERROR: Failed to create TechnicalAnalysis"); Cleanup(); return INIT_FAILED; } g_manager = new CPositionManager(); if(g_manager == NULL) { Print("ERROR: Failed to create PositionManager"); Cleanup(); return INIT_FAILED; } // Initialize utilities if(!g_utils.Initialize(InpLogLevel, InpSaveReports, InpInstanceID)) { Print("ERROR: Failed to initialize Utilities"); Cleanup(); return INIT_FAILED; } // Initialize risk manager if(!g_risk.Initialize(g_utils, InpMaxLossPerTrade, InpMaxDailyLoss, InpMaxDrawdown)) { Print("ERROR: Failed to initialize RiskManager"); Cleanup(); return INIT_FAILED; } // Initialize technical analysis if(!g_tech.Initialize(g_utils)) { Print("ERROR: Failed to initialize TechnicalAnalysis"); Cleanup(); return INIT_FAILED; } // Initialize position manager if(!g_manager.Initialize(g_utils, g_risk, g_tech, InpMagicFilter)) { Print("ERROR: Failed to initialize PositionManager"); Cleanup(); return INIT_FAILED; } // Configure position manager ManagementConfig config; config.apply_default_sl = InpApplyEmergencyStops; config.default_sl_atr = InpEmergencySLMultiplier; config.apply_default_tp = InpApplyEmergencyStops; config.default_tp_atr = InpEmergencyTPMultiplier; config.dynamic_sl_adjust = InpDynamicStops; config.tighten_on_profit = InpTightenOnProfit; config.tighten_threshold = InpTightenThreshold; config.breakeven_enabled = InpBreakevenEnabled; config.breakeven_trigger = InpBreakevenTrigger; config.breakeven_offset = InpBreakevenOffset; config.multi_level_be = InpMultiLevelBE; config.trailing_method = InpTrailingMethod; config.trail_start = InpTrailStart; config.trail_distance = InpTrailDistance; config.trail_step = InpTrailStep; config.adaptive_trailing = InpAdaptiveTrailing; config.partial_enabled = InpPartialEnabled; config.partial_trigger_1 = InpPartialTrigger1; config.partial_percent_1 = InpPartialPercent1; config.partial_trigger_2 = InpPartialTrigger2; config.partial_percent_2 = InpPartialPercent2; config.time_based_mgmt = InpTimeBasedExits; config.max_bars_in_trade = InpMaxBarsInTrade; config.reduce_risk_overtime = InpReduceRiskOverTime; config.friday_close_hour = InpFridayCloseHour; config.max_loss_per_trade = InpMaxLossPerTrade; config.max_daily_loss = InpMaxDailyLoss; config.max_correlation = InpMaxCorrelation; config.max_drawdown = InpMaxDrawdown; g_manager.SetConfiguration(config); // Initialize session g_session_start = TimeCurrent(); g_session_start_balance = AccountInfoDouble(ACCOUNT_BALANCE); g_session_start_equity = AccountInfoDouble(ACCOUNT_EQUITY); // Initialize dashboard if(InpShowDashboard) { InitializeDashboard(); } // Log configuration LogConfiguration(); // Set timer EventSetTimer(InpUpdateFrequency); g_initialized = true; // Initial status int initial_positions = g_manager.GetManagedCount(); Print(StringFormat("PME Ready - Managing %d positions", initial_positions)); g_utils.Log(StringFormat("PME initialized successfully - %d positions detected", initial_positions), LOG_INFO); // Sound alert if(InpSoundAlerts) PlaySound("alert.wav"); return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { EventKillTimer(); string reason_text = GetDeinitReasonText(reason); if(g_utils != NULL) { g_utils.Log(StringFormat("PME Shutdown: %s", reason_text), LOG_INFO); } // Generate final report if(g_manager != NULL && g_utils != NULL) { GenerateFinalReport(); } // Clean up dashboard if(InpShowDashboard) { RemoveDashboard(); } // Clean up components Cleanup(); Comment(""); Print("=================================================="); Print(StringFormat("PME Shutdown Complete: %s", reason_text)); Print("=================================================="); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { if(!g_initialized) return; // Check if we should be active if(!CheckTradingConditions()) return; // Main management cycle g_manager.ManageAllPositions(); // Check risk limits CheckRiskLimits(); // Update dashboard if visible if(InpShowDashboard) { UpdateDashboard(); } // Check for Friday close if(InpFridayClose && IsFridayClose()) { g_utils.Log("Friday close time - closing all positions", LOG_WARNING); g_manager.CloseAllPositions(EXIT_TIME); if(InpSoundAlerts) PlaySound("alert2.wav"); } } //+------------------------------------------------------------------+ //| Timer function | //+------------------------------------------------------------------+ void OnTimer() { if(!g_initialized) return; // Periodic status update static int status_counter = 0; status_counter++; if(status_counter >= 60 / InpUpdateFrequency) // Every minute { status_counter = 0; LogStatus(); } // Save snapshot static int snapshot_counter = 0; snapshot_counter++; if(snapshot_counter >= 300 / InpUpdateFrequency) // Every 5 minutes { snapshot_counter = 0; if(InpSaveReports) { SaveSnapshot(); } } // Check for alerts CheckAlerts(); } //+------------------------------------------------------------------+ //| Trade function | //+------------------------------------------------------------------+ void OnTrade() { if(!g_initialized) return; // Update metrics on trade events g_positions_closed++; // Log trade event if(g_utils != NULL) { g_utils.Log("Trade event detected", LOG_DEBUG); } } //+------------------------------------------------------------------+ //| Validate Inputs | //+------------------------------------------------------------------+ bool ValidateInputs() { if(InpMaxLossPerTrade <= 0 || InpMaxLossPerTrade > 10) { Print("Invalid MaxLossPerTrade: must be between 0 and 10"); return false; } if(InpMaxDailyLoss <= 0 || InpMaxDailyLoss > 20) { Print("Invalid MaxDailyLoss: must be between 0 and 20"); return false; } if(InpMaxDrawdown <= 0 || InpMaxDrawdown > 50) { Print("Invalid MaxDrawdown: must be between 0 and 50"); return false; } if(InpBreakevenTrigger < 5 || InpBreakevenTrigger > 1000) { Print("Invalid BreakevenTrigger: must be between 5 and 1000"); return false; } if(InpTrailDistance < 5 || InpTrailDistance > 1000) { Print("Invalid TrailDistance: must be between 5 and 1000"); return false; } return true; } //+------------------------------------------------------------------+ //| Check Trading Conditions | //+------------------------------------------------------------------+ bool CheckTradingConditions() { // Check if terminal is connected if(!TerminalInfoInteger(TERMINAL_CONNECTED)) return false; // Check if trade is allowed if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) return false; // Check time filter if(InpUseTimeFilter) { MqlDateTime current; TimeToStruct(TimeCurrent(), current); if(current.hour < InpStartHour || current.hour >= InpEndHour) return false; } return true; } //+------------------------------------------------------------------+ //| Check Risk Limits | //+------------------------------------------------------------------+ void CheckRiskLimits() { // Check daily loss double daily_loss = g_risk.GetDailyLoss(); if(daily_loss > InpMaxDailyLoss) { g_utils.Log(StringFormat("Daily loss limit reached: %.2f%%", daily_loss), LOG_ERROR); g_manager.CloseAllPositions(EXIT_RISK); // Send alerts SendAlert("Daily loss limit reached!"); } // Check drawdown double drawdown = g_risk.GetDrawdown(); if(drawdown > InpMaxDrawdown) { g_utils.Log(StringFormat("Max drawdown reached: %.2f%%", drawdown), LOG_ERROR); g_manager.CloseAllPositions(EXIT_DRAWDOWN); // Send alerts SendAlert("Max drawdown reached!"); } // Check individual position risks double total_risk = g_manager.GetTotalRisk(); double balance = AccountInfoDouble(ACCOUNT_BALANCE); double risk_percent = (total_risk / balance) * 100; if(risk_percent > InpMaxDailyLoss) { g_utils.Log(StringFormat("Total risk too high: %.2f%%", risk_percent), LOG_WARNING); } } //+------------------------------------------------------------------+ //| Check if Friday Close | //+------------------------------------------------------------------+ bool IsFridayClose() { MqlDateTime current; TimeToStruct(TimeCurrent(), current); return (current.day_of_week == 5 && current.hour >= InpFridayCloseHour); } //+------------------------------------------------------------------+ //| Initialize Dashboard | //+------------------------------------------------------------------+ void InitializeDashboard() { int y = InpDashboardY; color text_color = clrWhite; color header_color = clrGold; // Background CreateRectangle(g_dashboard_prefix + "BG", InpDashboardX - 5, y - 5, 250, 400, clrBlack, STYLE_SOLID, 1); // Header CreateLabel(g_dashboard_prefix + "HEADER", InpDashboardX, y, "ERMT PME v1.0", header_color, 11); y += 20; CreateLabel(g_dashboard_prefix + "LINE1", InpDashboardX, y, "────────────────────", text_color, 9); y += 15; // Status section CreateLabel(g_dashboard_prefix + "STATUS", InpDashboardX, y, "STATUS", header_color, 10); y += 18; CreateLabel(g_dashboard_prefix + "ACTIVE", InpDashboardX, y, "Active: 0", text_color, 9); y += 15; CreateLabel(g_dashboard_prefix + "CLOSED", InpDashboardX, y, "Closed: 0", text_color, 9); y += 20; // Risk section CreateLabel(g_dashboard_prefix + "RISK", InpDashboardX, y, "RISK", header_color, 10); y += 18; CreateLabel(g_dashboard_prefix + "EXPOSURE", InpDashboardX, y, "Exposure: 0.00", text_color, 9); y += 15; CreateLabel(g_dashboard_prefix + "DRAWDOWN", InpDashboardX, y, "Drawdown: 0.0%", text_color, 9); y += 20; // Management section CreateLabel(g_dashboard_prefix + "MGMT", InpDashboardX, y, "MANAGEMENT", header_color, 10); y += 18; CreateLabel(g_dashboard_prefix + "BREAKEVENS", InpDashboardX, y, "Breakevens: 0", text_color, 9); y += 15; CreateLabel(g_dashboard_prefix + "TRAILS", InpDashboardX, y, "Trails: 0", text_color, 9); y += 15; CreateLabel(g_dashboard_prefix + "PARTIALS", InpDashboardX, y, "Partials: 0", text_color, 9); y += 20; // Performance section CreateLabel(g_dashboard_prefix + "PERF", InpDashboardX, y, "PERFORMANCE", header_color, 10); y += 18; CreateLabel(g_dashboard_prefix + "SAVED", InpDashboardX, y, "Saved: $0.00", text_color, 9); y += 15; CreateLabel(g_dashboard_prefix + "CAPTURED", InpDashboardX, y, "Captured: $0.00", text_color, 9); y += 15; CreateLabel(g_dashboard_prefix + "EFFICIENCY", InpDashboardX, y, "Efficiency: 0.0%", text_color, 9); g_dashboard_objects = 20; // Track number of objects } //+------------------------------------------------------------------+ //| Update Dashboard | //+------------------------------------------------------------------+ void UpdateDashboard() { SessionMetrics metrics; g_manager.GetSessionMetrics(metrics); // Update status UpdateLabel(g_dashboard_prefix + "ACTIVE", StringFormat("Active: %d", g_manager.GetManagedCount())); UpdateLabel(g_dashboard_prefix + "CLOSED", StringFormat("Closed: %d", metrics.positions_closed)); // Update risk UpdateLabel(g_dashboard_prefix + "EXPOSURE", StringFormat("Exposure: %.2f", g_manager.GetTotalExposure())); UpdateLabel(g_dashboard_prefix + "DRAWDOWN", StringFormat("Drawdown: %.1f%%", g_risk.GetDrawdown())); // Update management UpdateLabel(g_dashboard_prefix + "BREAKEVENS", StringFormat("Breakevens: %d", metrics.breakevens_applied)); UpdateLabel(g_dashboard_prefix + "TRAILS", StringFormat("Trails: %d", metrics.trails_activated)); UpdateLabel(g_dashboard_prefix + "PARTIALS", StringFormat("Partials: %d", metrics.partial_closes)); // Update performance UpdateLabel(g_dashboard_prefix + "SAVED", StringFormat("Saved: $%.2f", metrics.total_prevented_loss)); UpdateLabel(g_dashboard_prefix + "CAPTURED", StringFormat("Captured: $%.2f", metrics.total_captured_profit)); UpdateLabel(g_dashboard_prefix + "EFFICIENCY", StringFormat("Efficiency: %.1f%%", metrics.management_efficiency)); // Update comment if dashboard not shown if(!InpShowDashboard) { Comment(StringFormat( "PME v1.0 | Active: %d | P/L: %.2f | Saved: %.2f | Efficiency: %.1f%%", g_manager.GetManagedCount(), g_manager.GetTotalProfit(), metrics.total_prevented_loss + metrics.total_captured_profit, metrics.management_efficiency )); } } //+------------------------------------------------------------------+ //| Remove Dashboard | //+------------------------------------------------------------------+ void RemoveDashboard() { for(int i = 0; i < g_dashboard_objects + 10; i++) { string name = g_dashboard_prefix + IntegerToString(i); ObjectDelete(0, name); } // Remove named objects ObjectDelete(0, g_dashboard_prefix + "BG"); ObjectDelete(0, g_dashboard_prefix + "HEADER"); ObjectDelete(0, g_dashboard_prefix + "LINE1"); ObjectDelete(0, g_dashboard_prefix + "STATUS"); ObjectDelete(0, g_dashboard_prefix + "ACTIVE"); ObjectDelete(0, g_dashboard_prefix + "CLOSED"); ObjectDelete(0, g_dashboard_prefix + "RISK"); ObjectDelete(0, g_dashboard_prefix + "EXPOSURE"); ObjectDelete(0, g_dashboard_prefix + "DRAWDOWN"); ObjectDelete(0, g_dashboard_prefix + "MGMT"); ObjectDelete(0, g_dashboard_prefix + "BREAKEVENS"); ObjectDelete(0, g_dashboard_prefix + "TRAILS"); ObjectDelete(0, g_dashboard_prefix + "PARTIALS"); ObjectDelete(0, g_dashboard_prefix + "PERF"); ObjectDelete(0, g_dashboard_prefix + "SAVED"); ObjectDelete(0, g_dashboard_prefix + "CAPTURED"); ObjectDelete(0, g_dashboard_prefix + "EFFICIENCY"); } //+------------------------------------------------------------------+ //| Create Label | //+------------------------------------------------------------------+ void CreateLabel(string name, int x, int y, string text, color clr, int size) { ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y); ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetString(0, name, OBJPROP_TEXT, text); ObjectSetString(0, name, OBJPROP_FONT, "Arial"); ObjectSetInteger(0, name, OBJPROP_FONTSIZE, size); ObjectSetInteger(0, name, OBJPROP_COLOR, clr); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); } //+------------------------------------------------------------------+ //| Update Label | //+------------------------------------------------------------------+ void UpdateLabel(string name, string text) { if(ObjectFind(0, name) >= 0) { ObjectSetString(0, name, OBJPROP_TEXT, text); } } //+------------------------------------------------------------------+ //| Create Rectangle | //+------------------------------------------------------------------+ void CreateRectangle(string name, int x, int y, int width, int height, color clr, ENUM_LINE_STYLE style, int line_width) { ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y); ObjectSetInteger(0, name, OBJPROP_XSIZE, width); ObjectSetInteger(0, name, OBJPROP_YSIZE, height); ObjectSetInteger(0, name, OBJPROP_BGCOLOR, clr); ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT); ObjectSetInteger(0, name, OBJPROP_WIDTH, line_width); ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, name, OBJPROP_STYLE, style); ObjectSetInteger(0, name, OBJPROP_BACK, false); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, name, OBJPROP_HIDDEN, true); } //+------------------------------------------------------------------+ //| Log Configuration | //+------------------------------------------------------------------+ void LogConfiguration() { if(g_utils == NULL) return; g_utils.Log("=== PME Configuration ===", LOG_INFO); g_utils.Log(StringFormat("Magic Filter: %d", InpMagicFilter), LOG_INFO); g_utils.Log(StringFormat("Management Mode: %s", ManagementModeToString(InpDefaultMode)), LOG_INFO); g_utils.Log(StringFormat("Max Loss/Trade: %.2f%%", InpMaxLossPerTrade), LOG_INFO); g_utils.Log(StringFormat("Max Daily Loss: %.2f%%", InpMaxDailyLoss), LOG_INFO); g_utils.Log(StringFormat("Max Drawdown: %.2f%%", InpMaxDrawdown), LOG_INFO); g_utils.Log(StringFormat("Breakeven: %s @ %.0f points", InpBreakevenEnabled ? "Enabled" : "Disabled", InpBreakevenTrigger), LOG_INFO); g_utils.Log(StringFormat("Trailing: %s", TrailingMethodToString(InpTrailingMethod)), LOG_INFO); g_utils.Log(StringFormat("Partial Close: %s", InpPartialEnabled ? "Enabled" : "Disabled"), LOG_INFO); g_utils.Log(StringFormat("Start Balance: %.2f", g_session_start_balance), LOG_INFO); g_utils.Log("========================", LOG_INFO); } //+------------------------------------------------------------------+ //| Log Status | //+------------------------------------------------------------------+ void LogStatus() { if(g_utils == NULL || g_manager == NULL) return; SessionMetrics metrics; g_manager.GetSessionMetrics(metrics); g_utils.Log(StringFormat( "Status: Active=%d | Closed=%d | BE=%d | Trails=%d | Saved=%.2f | Captured=%.2f", g_manager.GetManagedCount(), metrics.positions_closed, metrics.breakevens_applied, metrics.trails_activated, metrics.total_prevented_loss, metrics.total_captured_profit ), LOG_INFO); } //+------------------------------------------------------------------+ //| Save Snapshot | //+------------------------------------------------------------------+ void SaveSnapshot() { if(g_utils == NULL || g_manager == NULL) return; SessionMetrics metrics; g_manager.GetSessionMetrics(metrics); string filename = StringFormat("PME_Snapshot_%s.csv", TimeToString(TimeCurrent(), TIME_DATE)); string content = StringFormat( "%s,%d,%d,%d,%d,%d,%.2f,%.2f,%.2f,%.2f\n", TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES), g_manager.GetManagedCount(), metrics.positions_closed, metrics.breakevens_applied, metrics.trails_activated, metrics.partial_closes, metrics.total_prevented_loss, metrics.total_captured_profit, metrics.management_efficiency, AccountInfoDouble(ACCOUNT_BALANCE) ); g_utils.SaveToFile(filename, content, true); // Append mode } //+------------------------------------------------------------------+ //| Generate Final Report | //+------------------------------------------------------------------+ void GenerateFinalReport() { if(g_utils == NULL || g_manager == NULL) return; SessionMetrics metrics; g_manager.GetSessionMetrics(metrics); double session_duration = (TimeCurrent() - g_session_start) / 3600.0; // Hours double final_balance = AccountInfoDouble(ACCOUNT_BALANCE); double session_profit = final_balance - g_session_start_balance; string report = "\n"; report += "==================================================\n"; report += " ERMT PME - Final Session Report\n"; report += "==================================================\n"; report += StringFormat("Session Duration: %.1f hours\n", session_duration); report += StringFormat("Starting Balance: $%.2f\n", g_session_start_balance); report += StringFormat("Final Balance: $%.2f\n", final_balance); report += StringFormat("Session P/L: $%.2f (%.2f%%)\n", session_profit, (session_profit / g_session_start_balance) * 100); report += "\n"; report += "--- Management Statistics ---\n"; report += StringFormat("Positions Managed: %d\n", metrics.total_managed); report += StringFormat("Positions Closed: %d\n", metrics.positions_closed); report += StringFormat("Emergency Closes: %d\n", metrics.emergency_closes); report += "\n"; report += "--- Actions Taken ---\n"; report += StringFormat("Stops Added: %d\n", metrics.stops_added); report += StringFormat("Stops Adjusted: %d\n", metrics.stops_adjusted); report += StringFormat("Breakevens Applied: %d\n", metrics.breakevens_applied); report += StringFormat("Trails Activated: %d\n", metrics.trails_activated); report += StringFormat("Partial Closes: %d\n", metrics.partial_closes); report += StringFormat("Total Actions: %d\n", metrics.total_actions); report += "\n"; report += "--- Performance Metrics ---\n"; report += StringFormat("Loss Prevented: $%.2f\n", metrics.total_prevented_loss); report += StringFormat("Profit Captured: $%.2f\n", metrics.total_captured_profit); report += StringFormat("Total Value Added: $%.2f\n", metrics.total_prevented_loss + metrics.total_captured_profit); report += StringFormat("Management Efficiency: %.2f%%\n", metrics.management_efficiency); report += StringFormat("Success Rate: %.2f%%\n", metrics.success_rate); report += "\n"; report += "--- Risk Metrics ---\n"; report += StringFormat("Risk Reduced: $%.2f\n", metrics.total_risk_reduced); report += StringFormat("Avg Risk Reduction: %.2f%%\n", metrics.average_risk_reduction); report += StringFormat("Max Single Risk: $%.2f\n", metrics.max_single_risk); report += StringFormat("Final Exposure: $%.2f\n", metrics.current_exposure); report += "==================================================\n"; g_utils.Log(report, LOG_INFO); if(InpSaveReports) { string filename = StringFormat("PME_FinalReport_%s.txt", TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES)); g_utils.SaveToFile(filename, report, false); } } //+------------------------------------------------------------------+ //| Check Alerts | //+------------------------------------------------------------------+ void CheckAlerts() { if(TimeCurrent() - g_last_alert < 60) return; // Max 1 alert per minute // Check for positions without stops SessionMetrics metrics; g_manager.GetSessionMetrics(metrics); // Alert conditions bool alert_needed = false; string alert_message = ""; // Check drawdown double drawdown = g_risk.GetDrawdown(); if(drawdown > InpMaxDrawdown * 0.8) // 80% of max { alert_needed = true; alert_message = StringFormat("Warning: Drawdown at %.1f%%", drawdown); } // Check daily loss double daily_loss = g_risk.GetDailyLoss(); if(daily_loss > InpMaxDailyLoss * 0.8) // 80% of max { alert_needed = true; alert_message = StringFormat("Warning: Daily loss at %.1f%%", daily_loss); } if(alert_needed) { SendAlert(alert_message); g_last_alert = TimeCurrent(); } } //+------------------------------------------------------------------+ //| Send Alert | //+------------------------------------------------------------------+ void SendAlert(string message) { string full_message = StringFormat("PME Alert: %s", message); // Terminal alert Alert(full_message); // Sound alert if(InpSoundAlerts) { PlaySound("alert2.wav"); } // Email alert if(InpEmailAlerts) { SendMail("PME Alert", full_message); } // Push notification if(InpPushAlerts) { SendNotification(full_message); } // Log if(g_utils != NULL) { g_utils.Log(full_message, LOG_WARNING); } g_alert_count++; } //+------------------------------------------------------------------+ //| Get Deinitialization Reason Text | //+------------------------------------------------------------------+ string GetDeinitReasonText(int reason) { switch(reason) { case REASON_PROGRAM: return "Program terminated"; case REASON_REMOVE: return "Removed from chart"; case REASON_RECOMPILE: return "Recompiled"; case REASON_CHARTCHANGE: return "Chart changed"; case REASON_CHARTCLOSE: return "Chart closed"; case REASON_PARAMETERS: return "Parameters changed"; case REASON_ACCOUNT: return "Account changed"; case REASON_TEMPLATE: return "Template applied"; case REASON_INITFAILED: return "Initialization failed"; case REASON_CLOSE: return "Terminal closed"; default: return StringFormat("Unknown (%d)", reason); } } //+------------------------------------------------------------------+ //| Cleanup | //+------------------------------------------------------------------+ void Cleanup() { if(g_manager != NULL) { delete g_manager; g_manager = NULL; } if(g_tech != NULL) { delete g_tech; g_tech = NULL; } if(g_risk != NULL) { delete g_risk; g_risk = NULL; } if(g_utils != NULL) { delete g_utils; g_utils = NULL; } } //+------------------------------------------------------------------+