Migrating an Expert Advisor from MQL4 to MQL5 demands handling fundamental differences in trade execution, tick processing, and historical data access. The most immediate change is replacing `OrderSend()` with the `CTrade` class.
1. Trade Execution: OrderSend → CTrade
In MQL4, opening a buy order:
```cpp
int ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "EA", 0, 0, Green);
```
MQL5 equivalent using `CTrade`:
```cpp
#include
CTrade trade;
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
trade.PositionOpen(_Symbol, ORDER_TYPE_BUY, 0.1, ask, 0, 0, "EA");
```
Note: MQL5 requires explicit symbol info fetching. Slippage is handled via `trade.SetDeviationInPoints()`.
2. Tick and Volume Model
MQL4’s `Volume` is tick count; MQL5 uses real volume. For backtest compatibility, normalize:
```cpp
// MQL5: convert tick volume to approximate lot-based volume
long tickVolume = (long)MathRound(volumeReal / SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP));
```
3. Order Selection and Loop
MQL4 uses `OrderSelect()` with a global pool. MQL5 uses positions and orders separated:
```cpp
// MQL5 position loop
for(int i = PositionsTotal()-1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket)) {
double profit = PositionGetDouble(POSITION_PROFIT);
}
}
```
4. Backtest Adaptation: Removing Future Functions
MQL4 allows `Volume[0]` (current tick). MQL5 requires `CopyTicks()` with a flag to avoid look-ahead bias. Always use `COPY_TICKS_ALL` and process with a delay.
5. Complete Migration Function Example
```cpp
// MQL5: Open limit order with error handling
bool OpenLimitOrder(double price, double lot) {
CTrade trade;
trade.SetTypeFilling(ORDER_FILLING_IOC);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if(!trade.OrderOpen(_Symbol, ORDER_TYPE_BUY_LIMIT, lot, price, 0, 0, "MigratedEA"))
return false;
return true;
}
```
Reference: MQL5 Community, "Migration from MQL4 to MQL5" (mql5.com/docs/migration), 2024.