Summary: Advanced MT4 to MT5 EA migration techniques covering order pooling, historical order selection with time filters, and event handler differences. Runnable code examples for professional EA porting.




Migrating from MT4 to MT5 requires reworking order management, history access, and event structure. Two critical areas often break: position vs order separation, and historical data retrieval with time filters.

1. Order Pool: No Global Selection
MQL4 uses a single pool with `OrderSelect()`. MQL5 separates positions, pending orders, and history:
```cpp
// MQL4 style (deprecated in MQL5)
for(int i=0; i if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
double op = OrderOpenPrice();
}
}

// MQL5 correct: iterate positions
for(int i= PositionsTotal()-1; i>=0; i--) {
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket)) {
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double profit = PositionGetDouble(POSITION_PROFIT);
}
}
```

2. HistorySelect: Time Range Mandatory
MQL4's `OrderSelect()` works without time filters. MQL5 requires `HistorySelect()` before accessing historical orders:
```cpp
// MQL5: select last 30 days of history
datetime from = TimeCurrent() - 30*24*3600;
datetime to = TimeCurrent();
if(HistorySelect(from, to)) {
int total = HistoryDealsTotal(); // not OrdersTotal()
for(int i=0; i ulong ticket = HistoryDealGetTicket(i);
double price = HistoryDealGetDouble(ticket, DEAL_PRICE);
}
}
```
Without `HistorySelect()`, `HistoryDealsTotal()` returns 0.

3. Event Handler Differences
MQL4's `init()` and `deinit()` become `OnInit()` and `OnDeinit()`. MQL5 adds `OnTimer()` and `OnTrade()`:
```cpp
// MQL5 event handlers
int OnInit() {
EventSetTimer(60); // 60-second timer
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason) {
EventKillTimer();
}
void OnTimer() {
// periodic logic, e.g., trailing stop
}
void OnTrade() {
// triggered on any trade event (fill, modification)
}
```

4. Complete Migration Utility Function
Get total net profit across closed and open positions:
```cpp
double GetTotalNetProfit() {
double profit = 0;
// closed profit from history
datetime from = 0;
datetime to = TimeCurrent();
HistorySelect(from, to);
for(int i=0; i ulong ticket = HistoryDealGetTicket(i);
if(HistoryDealGetInteger(ticket, DEAL_TYPE) == DEAL_TYPE_SELL ||
HistoryDealGetInteger(ticket, DEAL_TYPE) == DEAL_TYPE_BUY) {
profit += HistoryDealGetDouble(ticket, DEAL_PROFIT);
}
}
// open positions profit
for(int i=0; i ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket))
profit += PositionGetDouble(POSITION_PROFIT);
}
return profit;
}
```

Reference: MQL5 Documentation, "History and Orders in MQL5" (mql5.com/en/docs/trading/history), 2025.