Even well-built trading systems encounter issues. This guide provides systematic approaches to identify and fix problems in your automated trading.
Common Issues Categories
Connection Problems
- Broker server unavailable
- Network timeouts
- Authentication failures
- WebRequest blocked
Logic Errors
- Wrong signal generation
- Incorrect position sizing
- Missing trade conditions
- Order type mismatches
Execution Issues
- Order rejection
- Slippage beyond limits
- Partial fills
- Wrong price execution
Resource Problems
- Memory leaks
- CPU overload
- Disk space full
- Handle exhaustion
MQL5 Debugging Techniques
Using Print Statements
// Basic logging
Print("Signal generated: ", signal, " at ", TimeCurrent());
// Detailed debug function
void Debug(string function, string message)
{
Print("[DEBUG] ", function, ": ", message);
}
// Usage
void OnTick()
{
Debug("OnTick", "New tick received");
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
Debug("OnTick", "Bid price: " + DoubleToString(bid, _Digits));
int signal = GenerateSignal();
Debug("OnTick", "Signal value: " + IntegerToString(signal));
}
Conditional Debugging
input bool EnableDebug = true;
input int DebugLevel = 2; // 1=Basic, 2=Detailed, 3=Verbose
void Log(int level, string message)
{
if(!EnableDebug) return;
if(level > DebugLevel) return;
string prefix = "";
switch(level)
{
case 1: prefix = "[INFO] "; break;
case 2: prefix = "[DEBUG] "; break;
case 3: prefix = "[TRACE] "; break;
}
Print(prefix, message);
}
// Usage
Log(1, "EA started");
Log(2, "Checking signal conditions");
Log(3, "MA Fast: " + DoubleToString(maFast, 5));
Error Code Handling
void HandleError(string operation)
{
int error = GetLastError();
if(error == 0) return;
string errorMsg = "";
switch(error)
{
case 10004: errorMsg = "Requote"; break;
case 10006: errorMsg = "Request rejected"; break;
case 10007: errorMsg = "Request canceled by trader"; break;
case 10010: errorMsg = "Only position closing allowed"; break;
case 10011: errorMsg = "Position closing only"; break;
case 10012: errorMsg = "Invalid volume"; break;
case 10013: errorMsg = "Invalid price"; break;
case 10014: errorMsg = "Invalid stops"; break;
case 10015: errorMsg = "Trade disabled"; break;
case 10016: errorMsg = "Market closed"; break;
case 10017: errorMsg = "Not enough money"; break;
case 10018: errorMsg = "Price changed"; break;
case 10019: errorMsg = "No quotes"; break;
case 10020: errorMsg = "Invalid order expiration"; break;
case 10021: errorMsg = "Order changed"; break;
case 10022: errorMsg = "Too many requests"; break;
default: errorMsg = "Unknown error: " + IntegerToString(error);
}
Print("[ERROR] ", operation, " failed: ", errorMsg);
Alert(operation, " error: ", errorMsg);
}
// Usage
MqlTradeResult result;
if(!OrderSend(request, result))
{
HandleError("OrderSend");
}
Variable State Tracking
void PrintTradeRequest(MqlTradeRequest& request)
{
Print("=== Trade Request ===");
Print("Action: ", EnumToString((ENUM_TRADE_REQUEST_ACTIONS)request.action));
Print("Symbol: ", request.symbol);
Print("Volume: ", request.volume);
Print("Type: ", EnumToString((ENUM_ORDER_TYPE)request.type));
Print("Price: ", request.price);
Print("SL: ", request.sl);
Print("TP: ", request.tp);
Print("Deviation: ", request.deviation);
Print("Magic: ", request.magic);
Print("====================");
}
void PrintTradeResult(MqlTradeResult& result)
{
Print("=== Trade Result ===");
Print("Retcode: ", result.retcode);
Print("Deal: ", result.deal);
Print("Order: ", result.order);
Print("Volume: ", result.volume);
Print("Price: ", result.price);
Print("Comment: ", result.comment);
Print("====================");
}
Python Debugging
Logging Setup
import logging
from datetime import datetime
def setup_logger(name, log_file, level=logging.DEBUG):
"""Setup logger with file and console handlers"""
logger = logging.getLogger(name)
logger.setLevel(level)
# File handler
fh = logging.FileHandler(log_file)
fh.setLevel(logging.DEBUG)
# Console handler
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
# Format
formatter = logging.Formatter(
'%(asctime)s | %(name)s | %(levelname)s | %(message)s'
)
fh.setFormatter(formatter)
ch.setFormatter(formatter)
logger.addHandler(fh)
logger.addHandler(ch)
return logger
# Usage
logger = setup_logger('trading_bot', 'logs/trading.log')
logger.debug("Detailed debug info")
logger.info("General info")
logger.warning("Warning message")
logger.error("Error occurred")
logger.critical("Critical failure")
Exception Handling
import traceback
class TradingBot:
def __init__(self):
self.logger = setup_logger('bot', 'bot.log')
def execute_trade(self, symbol, direction, volume):
"""Execute trade with comprehensive error handling"""
try:
self.logger.info(f"Executing {direction} {volume} {symbol}")
# Validate inputs
if volume <= 0:
raise ValueError(f"Invalid volume: {volume}")
if direction not in ['buy', 'sell']:
raise ValueError(f"Invalid direction: {direction}")
# Execute
result = self.broker.place_order(symbol, direction, volume)
self.logger.info(f"Trade executed: {result}")
return result
except ValueError as e:
self.logger.error(f"Validation error: {e}")
raise
except ConnectionError as e:
self.logger.error(f"Connection error: {e}")
self.logger.info("Attempting reconnection...")
self.reconnect()
except Exception as e:
self.logger.critical(f"Unexpected error: {e}")
self.logger.debug(traceback.format_exc())
raise
Debug Context Manager
import time
class DebugTimer:
"""Context manager for timing code blocks"""
def __init__(self, name, logger):
self.name = name
self.logger = logger
def __enter__(self):
self.start = time.time()
return self
def __exit__(self, *args):
elapsed = time.time() - self.start
self.logger.debug(f"{self.name} took {elapsed:.4f}s")
# Usage
with DebugTimer("Signal calculation", logger):
signal = calculate_signal(data)
with DebugTimer("Order execution", logger):
result = place_order(signal)
Common Issues and Solutions
Issue: EA Not Opening Trades
Symptoms: Signal generated but no trades
Debug Steps:
void DiagnoseNoTrades()
{
Print("=== Diagnosing No Trades ===");
// Check AutoTrading
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
{
Print("AutoTrading is DISABLED in terminal");
return;
}
// Check EA permissions
if(!MQLInfoInteger(MQL_TRADE_ALLOWED))
{
Print("EA trading is NOT allowed");
return;
}
// Check account
if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED))
{
Print("Account trading is DISABLED");
return;
}
// Check market
if(!SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE))
{
Print("Symbol trading is DISABLED");
return;
}
// Check spread
double spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
Print("Current spread: ", spread);
// Check balance
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double freeMargin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
Print("Balance: ", balance, " Free margin: ", freeMargin);
Print("All basic checks passed");
}
Issue: Orders Being Rejected
void DiagnoseOrderRejection(MqlTradeResult& result)
{
Print("=== Order Rejection Diagnosis ===");
Print("Retcode: ", result.retcode);
switch(result.retcode)
{
case 10016:
Print("Market is closed");
Print("Check trading hours for ", _Symbol);
break;
case 10017:
Print("Insufficient funds");
Print("Required margin: Check position size");
Print("Free margin: ", AccountInfoDouble(ACCOUNT_MARGIN_FREE));
break;
case 10014:
Print("Invalid stops");
Print("Check minimum stop distance");
double stopLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
Print("Minimum stop distance: ", stopLevel);
break;
case 10012:
Print("Invalid volume");
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
Print("Min lot: ", minLot, " Max: ", maxLot, " Step: ", lotStep);
break;
}
}
Issue: Unexpected Position Sizes
`mql5 void ValidateLotSize(double requestedLots) { double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
Print("Requested lots: ", requestedLots); Print("Min: ", minLot, " Max: ", maxLot, " Step: ", lotStep);
// Check minimum if(requestedLots < minLot) { Print("WARNING: Lots below minimum, will be adjusted to ", minLot); }
// Check step double normalized = MathFloor(requestedLots / lotStep) * lotStep; if(normalized != requestedLots) { Print("WARNING: Lots not aligned to step, will be ", normalized); }
// Check margin double margin; if(OrderCalcMargin(ORDER_TYPE_BUY, _Symbol, requestedLots, SymbolInfoDouble(_Symbol, SYMBOL_ASK), margin)) { Print("Required margin: ", margin); Print("Free margin: ", AccountInfoDouble(ACCOUNT_MARGIN_FREE));
if(margin > AccountInfoDouble(ACCOUNT_MARGIN_FREE)) { Print("ERROR: Insufficient margin for this lot size"); } } } `
Testing Strategies
Unit Testing EA Functions
void RunTests()
{
Print("=== Running EA Tests ===");
TestCalculateLotSize();
TestSignalGeneration();
TestStopLossCalculation();
Print("=== Tests Complete ===");
}
void TestCalculateLotSize()
{
Print("Testing CalculateLotSize...");
// Test case 1: Normal calculation
double lots = CalculateLotSize(1.0, 50); // 1% risk, 50 pip SL
if(lots > 0 && lots <= SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX))
{
Print(" Test 1 PASSED: lots = ", lots);
}
else
{
Print(" Test 1 FAILED: lots = ", lots);
}
// Test case 2: Zero stop loss
lots = CalculateLotSize(1.0, 0);
if(lots == 0)
{
Print(" Test 2 PASSED: Zero SL handled");
}
else
{
Print(" Test 2 FAILED: Zero SL not handled");
}
}
Backtesting Verification
`mql5 // Add to OnTester() for backtest verification double OnTester() { // Get statistics double profit = TesterStatistics(STAT_PROFIT); double trades = TesterStatistics(STAT_TRADES); double winRate = TesterStatistics(STAT_PROFIT_TRADES) / TesterStatistics(STAT_TRADES) * 100; double drawdown = TesterStatistics(STAT_EQUITY_DD_RELATIVE);
Print("=== Backtest Summary ==="); Print("Total Trades: ", trades); Print("Net Profit: ", profit); Print("Win Rate: ", winRate, "%"); Print("Max Drawdown: ", drawdown, "%");
// Validate results if(trades < 100) { Print("WARNING: Too few trades for reliable statistics"); }
if(drawdown > 30) { Print("WARNING: Excessive drawdown"); }
return profit; } ``
Debugging Checklist
Before Each Trading Session
- [ ] Check AutoTrading is enabled
- [ ] Verify broker connection
- [ ] Confirm account permissions
- [ ] Check symbol is tradable
- [ ] Review spread conditions
- [ ] Verify sufficient margin
- [ ] Check EA parameters
- [ ] Review journal for errors
When Issues Occur
- Check MT5 Journal and Experts tabs
- Review log files
- Verify market conditions
- Test with minimal lot size
- Check network connectivity
- Review recent changes
- Test on demo account
Key Takeaways
- Implement comprehensive logging from the start
- Use conditional debugging to control output
- Handle all error codes explicitly
- Create diagnostic functions for common issues
- Test EA functions independently
- Keep a debugging checklist
- Document all issues and solutions
- Test changes on demo before live
What's Next?
Learn about strategy optimization techniques to improve your trading system performance.
This article is for educational purposes only and does not constitute financial advice.