//+------------------------------------------------------------------+ //| PME_Diagnostic_Script.mq5 | //| Diagnose Why Positions Are Closing Early | //+------------------------------------------------------------------+ #property script_show_inputs #include "Modules_PME/DataTypes_PME.mqh" #include "Modules_PME/Utilities_PME.mqh" #include "Modules_PME/RiskManager_PME.mqh" #include "Modules_PME/TechnicalAnalysis_PME.mqh" #include "Modules_PME/PositionManager_PME.mqh" //+------------------------------------------------------------------+ //| Input Parameters | //+------------------------------------------------------------------+ input bool InpCheckCurrentPositions = true; // Check Current Positions input bool InpCheckExitConditions = true; // Check Exit Conditions input bool InpCheckRiskLimits = true; // Check Risk Limits input bool InpCheckTechnicalSignals = true; // Check Technical Signals input bool InpShowDetailedReport = true; // Show Detailed Report //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { Print("========================================"); Print(" PME DIAGNOSTIC ANALYSIS"); Print("========================================"); Print("Analyzing why positions might be closing early...\n"); // Initialize components CUtilities* utils = new CUtilities(); CRiskManager* risk = new CRiskManager(); CTechnicalAnalysis* tech = new CTechnicalAnalysis(); CPositionManager* manager = new CPositionManager(); // Initialize utils.Initialize(LOG_DEBUG, false); risk.Initialize(utils, 2.0, 6.0, 20.0); tech.Initialize(utils); manager.Initialize(utils, risk, tech, 0); // 1. CHECK CURRENT POSITIONS if(InpCheckCurrentPositions) { Print("\n--- CURRENT POSITIONS ---"); int total = PositionsTotal(); Print("Total positions: ", total); for(int i = 0; i < total; i++) { ulong ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket)) { string symbol = PositionGetString(POSITION_SYMBOL); ENUM_ORDER_TYPE type = (ENUM_ORDER_TYPE)PositionGetInteger(POSITION_TYPE); double volume = PositionGetDouble(POSITION_VOLUME); double profit = PositionGetDouble(POSITION_PROFIT); double sl = PositionGetDouble(POSITION_SL); double tp = PositionGetDouble(POSITION_TP); datetime open_time = (datetime)PositionGetInteger(POSITION_TIME); // Calculate bars in trade int bars = Bars(symbol, PERIOD_CURRENT, open_time, TimeCurrent()); Print("\nPosition #", ticket, ":"); Print(" Symbol: ", symbol, " | Type: ", EnumToString(type)); Print(" Volume: ", volume, " | Profit: ", DoubleToString(profit, 2)); Print(" SL: ", sl > 0 ? DoubleToString(sl, 5) : "NONE"); Print(" TP: ", tp > 0 ? DoubleToString(tp, 5) : "NONE"); Print(" Bars in trade: ", bars); // Check for issues if(sl == 0) Print(" ⚠️ WARNING: No stop loss!"); if(tp == 0) Print(" ⚠️ WARNING: No take profit!"); if(bars < 5) Print(" ⚠️ WARNING: Very new position (< 5 bars)"); } } } // 2. CHECK EXIT CONDITIONS if(InpCheckExitConditions) { Print("\n--- EXIT CONDITIONS ANALYSIS ---"); for(int i = 0; i < PositionsTotal(); i++) { ulong ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket)) { string symbol = PositionGetString(POSITION_SYMBOL); ENUM_ORDER_TYPE type = (ENUM_ORDER_TYPE)PositionGetInteger(POSITION_TYPE); double entry = PositionGetDouble(POSITION_PRICE_OPEN); double current = PositionGetDouble(POSITION_PRICE_CURRENT); double profit = PositionGetDouble(POSITION_PROFIT); Print("\nPosition #", ticket, " Exit Analysis:"); // Calculate profit in points double point = SymbolInfoDouble(symbol, SYMBOL_POINT); double profit_points = 0; if(type == ORDER_TYPE_BUY) profit_points = (current - entry) / point; else profit_points = (entry - current) / point; Print(" Profit: ", DoubleToString(profit, 2), " | Points: ", DoubleToString(profit_points, 1)); // Check various exit conditions // Breakeven check (default 20 points) if(profit_points >= 20 && profit_points < 30) Print(" 📊 Near breakeven trigger (20 pts)"); // Trail start check (default 30 points) if(profit_points >= 30 && profit_points < 50) Print(" 📊 Near trail start trigger (30 pts)"); // Partial close check (default 30 points) if(profit_points >= 30 && profit_points < 60) Print(" 📊 In partial close zone (30-60 pts)"); // Check if losing position if(profit < 0) { double balance = AccountInfoDouble(ACCOUNT_BALANCE); double loss_percent = MathAbs(profit / balance * 100); Print(" 📉 Losing position: -", DoubleToString(loss_percent, 2), "%"); if(loss_percent > 1.5) Print(" ⚠️ WARNING: Approaching max loss per trade limit!"); } } } } // 3. CHECK RISK LIMITS if(InpCheckRiskLimits) { Print("\n--- RISK LIMITS ANALYSIS ---"); double balance = AccountInfoDouble(ACCOUNT_BALANCE); double equity = AccountInfoDouble(ACCOUNT_EQUITY); double margin = AccountInfoDouble(ACCOUNT_MARGIN); double free_margin = AccountInfoDouble(ACCOUNT_MARGIN_FREE); Print("Balance: ", DoubleToString(balance, 2)); Print("Equity: ", DoubleToString(equity, 2)); Print("Margin: ", DoubleToString(margin, 2)); Print("Free Margin: ", DoubleToString(free_margin, 2)); // Check daily loss double daily_loss = risk.GetDailyLoss(); Print("\nDaily Loss: ", DoubleToString(daily_loss, 2), "%"); if(daily_loss > 4) Print(" ⚠️ WARNING: High daily loss (>4%)"); if(daily_loss > 6) Print(" 🚨 CRITICAL: Approaching daily loss limit (6%)!"); // Check drawdown double drawdown = risk.GetDrawdown(); Print("Drawdown: ", DoubleToString(drawdown, 2), "%"); if(drawdown > 10) Print(" ⚠️ WARNING: Significant drawdown (>10%)"); if(drawdown > 20) Print(" 🚨 CRITICAL: Approaching max drawdown limit (20%)!"); // Check total exposure double total_lots = 0; for(int i = 0; i < PositionsTotal(); i++) { if(PositionSelectByTicket(PositionGetTicket(i))) total_lots += PositionGetDouble(POSITION_VOLUME); } Print("\nTotal Exposure: ", DoubleToString(total_lots, 2), " lots"); // Margin level if(margin > 0) { double margin_level = (equity / margin) * 100; Print("Margin Level: ", DoubleToString(margin_level, 2), "%"); if(margin_level < 200) Print(" ⚠️ WARNING: Low margin level!"); } } // 4. CHECK TECHNICAL SIGNALS if(InpCheckTechnicalSignals) { Print("\n--- TECHNICAL SIGNALS ANALYSIS ---"); for(int i = 0; i < PositionsTotal(); i++) { ulong ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket)) { string symbol = PositionGetString(POSITION_SYMBOL); ENUM_ORDER_TYPE type = (ENUM_ORDER_TYPE)PositionGetInteger(POSITION_TYPE); double entry = PositionGetDouble(POSITION_PRICE_OPEN); double current = PositionGetDouble(POSITION_PRICE_CURRENT); Print("\nPosition #", ticket, " (", symbol, "):"); // Get indicators double rsi = tech.GetRSI(symbol); double ma20 = tech.GetMA(symbol); double atr = tech.GetATR(symbol); ENUM_MARKET_CONDITION market = tech.GetMarketCondition(symbol); Print(" RSI: ", DoubleToString(rsi, 1)); Print(" MA20: ", DoubleToString(ma20, 5)); Print(" ATR: ", DoubleToString(atr, 5)); Print(" Market: ", MarketConditionToString(market)); // Check exit conditions if(type == ORDER_TYPE_BUY) { if(rsi > 70) Print(" 📊 RSI Overbought (>70) - Potential exit signal"); if(rsi > 80) Print(" 🚨 RSI Extreme Overbought (>80) - Strong exit signal"); if(current < ma20) Print(" 📊 Price below MA20 - Weakness signal"); // Check if would exit ENUM_EXIT_REASON exit = tech.CheckExitSignal(symbol, type, entry, current); if(exit != EXIT_NONE) Print(" 🚨 TECHNICAL EXIT TRIGGERED: ", ExitReasonToString(exit)); } else // SELL { if(rsi < 30) Print(" 📊 RSI Oversold (<30) - Potential exit signal"); if(rsi < 20) Print(" 🚨 RSI Extreme Oversold (<20) - Strong exit signal"); if(current > ma20) Print(" 📊 Price above MA20 - Weakness signal"); // Check if would exit ENUM_EXIT_REASON exit = tech.CheckExitSignal(symbol, type, entry, current); if(exit != EXIT_NONE) Print(" 🚨 TECHNICAL EXIT TRIGGERED: ", ExitReasonToString(exit)); } } } } // 5. DETAILED REPORT if(InpShowDetailedReport) { Print("\n========================================"); Print(" DIAGNOSTIC SUMMARY"); Print("========================================"); Print("\n🔍 COMMON CAUSES OF PREMATURE CLOSING:"); Print("\n1. TECHNICAL EXITS:"); Print(" - RSI > 70 (longs) or < 30 (shorts)"); Print(" - Price crosses MA"); Print(" Solution: Disable InpUseTechnicalExits"); Print("\n2. TIME-BASED EXITS:"); Print(" - Max bars in trade (default 100)"); Print(" - Friday close"); Print(" Solution: Disable InpTimeBasedExits"); Print("\n3. RISK LIMITS:"); Print(" - Max loss per trade (2%)"); Print(" - Daily loss limit (6%)"); Print(" - Max drawdown (20%)"); Print(" Solution: Increase risk limits"); Print("\n4. PROFIT PROTECTION:"); Print(" - 50% retracement from peak"); Print(" Solution: Increase protection threshold"); Print("\n📋 RECOMMENDED ACTIONS:"); Print("1. Set InpUseTechnicalExits = false"); Print("2. Set InpTimeBasedExits = false"); Print("3. Set InpFridayClose = false"); Print("4. Increase breakeven trigger to 30+ points"); Print("5. Increase trail start to 50+ points"); Print("6. Review the optimized modules provided"); Print("\n✅ Use the optimized settings in:"); Print(" ERMT_PME_Optimized_Settings.mqh"); } // Cleanup delete manager; delete tech; delete risk; delete utils; Print("\n========================================"); Print(" DIAGNOSTIC COMPLETE"); Print("========================================"); } //+------------------------------------------------------------------+