301 行
13 KiB
MQL5
301 行
13 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| 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("========================================");
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|