Summary: 面向进阶用户的MT4转MT5迁移技术,详解订单池分离、带时间过滤的历史订单选择、事件处理器差异,附带可直接运行的代码示例,解决跨平台EA的常见隐痛。




从MT4迁移到MT5需要重构订单管理、历史访问和事件结构。最容易出错的两个环节是:持仓与挂单的分离模型,以及带时间过滤的历史数据获取。

1. 订单池:无全局选择
MQL4使用单一订单池配合`OrderSelect()`。MQL5将持仓、挂单、历史记录完全分离:
```cpp
// MQL4风格(MQL5中不可用)
for(int i=0; i if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
double op = OrderOpenPrice();
}
}

// MQL5正确写法:遍历持仓
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:必须指定时间范围
MQL4的`OrderSelect()`无需时间过滤。MQL5必须先调用`HistorySelect()`才能访问历史订单:
```cpp
// MQL5:选取最近30天历史
datetime from = TimeCurrent() - 30*24*3600;
datetime to = TimeCurrent();
if(HistorySelect(from, to)) {
int total = HistoryDealsTotal(); // 不是 OrdersTotal()
for(int i=0; i ulong ticket = HistoryDealGetTicket(i);
double price = HistoryDealGetDouble(ticket, DEAL_PRICE);
}
}
```
若不调用`HistorySelect()`,`HistoryDealsTotal()`始终返回0。

3. 事件处理器差异
MQL4的`init()`和`deinit()`变为`OnInit()`和`OnDeinit()`。MQL5新增`OnTimer()`和`OnTrade()`:
```cpp
// MQL5 事件处理器
int OnInit() {
EventSetTimer(60); // 60秒定时器
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason) {
EventKillTimer();
}
void OnTimer() {
// 定时逻辑,如移动止损
}
void OnTrade() {
// 任何交易事件触发(成交、修改)
}
```

4. 完整迁移工具函数
获取已平仓和持仓的总净盈利:
```cpp
double 获取总净盈利() {
double profit = 0;
// 已平仓盈利
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);
}
}
// 持仓浮动盈亏
for(int i=0; i ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket))
profit += PositionGetDouble(POSITION_PROFIT);
}
return profit;
}
```

参考来源:MQL5官方文档,《MQL5中的历史与订单》(mql5.com/en/docs/trading/history),2025。