The migration from MQL4 to MQL5 is not a simple syntax update. MQL5 fundamentally restructures how trades are managed: separate position and order concepts replace MQL4's unified order pool. Understanding this architectural shift is essential for any cross-platform EA migration.
Core Architectural Difference
MQL4 uses a single order pool where pending orders and market positions share the same ticket system and `OrderSelect()` mechanism. MQL5 separates:
MQL4 OrderSend to MQL5 Replacement
In MQL4, opening a position uses `OrderSend()`:
```cpp
// MQL4 - Original
int ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 3, stopLoss, takeProfit, "EA Comment", magic, 0, Green);
```
In MQL5, market positions and pending orders require separate functions:
```cpp
// MQL5 - Equivalent
// Open market position
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = Symbol();
request.volume = Lots;
request.type = ORDER_TYPE_BUY;
request.price = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
request.sl = stopLoss;
request.tp = takeProfit;
request.deviation = 3;
request.magic = magic;
request.comment = "EA Comment";
OrderSend(request, result);
ulong ticket = result.order;
```
Position Selection Pattern Migration
MQL4 iterative selection:
```cpp
for(int i = 0; i < OrdersTotal(); i++) {
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
if(OrderMagicNumber() == magic && OrderSymbol() == Symbol()) {
// Process order
}
}
}
```
MQL5 position iterator:
```cpp
for(int i = 0; i < PositionsTotal(); i++) {
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket)) {
if(PositionGetInteger(POSITION_MAGIC) == magic && PositionGetString(POSITION_SYMBOL) == Symbol()) {
// Process position
}
}
}
```
Mathematical Transformation for Risk Calculation
Position sizing formula remains consistent but requires different symbol info access:
MQL4: `MarketInfo(Symbol(), MODE_TICKVALUE)`
MQL5: `SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE)`
Risk-based lot calculation:
\[
\text{Lots} = \frac{\text{RiskPercent} \times \text{Balance}}{100 \times \text{StopLossPoints} \times \text{TickValue}}
\]
Where `TickValue` must be normalized to account for quote currency. For non-USD pairs, apply:
\[
\text{TickValue}_{\text{USD}} = \frac{\text{TickValue}_{\text{original}}}{\text{USDQuote}}
\]
Cross-Platform Compatible Order Send Macro
Use preprocessor directives to maintain single codebase:
```cpp
#ifdef __MQL4__
#define OPEN_BUY(Lots, Sl, Tp) OrderSend(Symbol(), OP_BUY, Lots, Ask, 3, Sl, Tp, "", magic, 0, Green)
#else
#define OPEN_BUY(Lots, Sl, Tp) OpenBuyMQL5(Lots, Sl, Tp)
#endif
```
History Access Migration
MQL4 selects closed orders by `OrderSelect()` with `MODE_HISTORY`. MQL5 uses `HistorySelect(startDate, endDate)` then iterates with `HistoryDealGetTicket()`.
Reference: MQL5 Documentation - Migration from MQL4 (https://www.mql5.com/en/docs/migration), "Expert Advisor Programming for MetaTrader 5" by Andrew R. Young, 2020.