将EA从MQL4迁移到MQL5需要处理交易执行、Tick处理和历史数据访问的底层差异。最直接的改变是将`OrderSend()`替换为`CTrade`类。
1. 交易执行:OrderSend → CTrade
MQL4开多单:
```cpp
int ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "EA", 0, 0, Green);
```
MQL5等价实现(使用`CTrade`):
```cpp
#include
CTrade trade;
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
trade.PositionOpen(_Symbol, ORDER_TYPE_BUY, 0.1, ask, 0, 0, "EA");
```
注意:MQL5需显式获取品种报价,滑点通过`trade.SetDeviationInPoints()`设置。
2. Tick与交易量模型
MQL4的`Volume`代表Tick次数,MQL5使用真实交易量。为保证回测兼容性:
```cpp
// MQL5:将Tick量近似转换为合约步长对应的交易量
long tickVolume = (long)MathRound(volumeReal / SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP));
```
3. 订单选择与遍历
MQL4通过`OrderSelect()`操作全局订单池。MQL5将持仓与挂单分离:
```cpp
// MQL5 遍历持仓
for(int i = PositionsTotal()-1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket)) {
double profit = PositionGetDouble(POSITION_PROFIT);
}
}
```
4. 回测适配:规避未来函数
MQL4中`Volume[0]`可访问当前未完成Tick,造成未来函数。MQL5需使用`CopyTicks()`并带延迟处理标志,例如仅处理已关闭时间戳的Tick。
5. 完整迁移函数示例
```cpp
// MQL5:带错误处理的挂限价单
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, "迁移EA"))
return false;
return true;
}
```
参考来源:MQL5官方社区,《从MQL4迁移到MQL5》(mql5.com/docs/migration),2024。