Summary: 本文详解MQL4与MQL5在EA开发中的关键差异:OrderSend替代、持仓与订单分离、票据系统变更。提供可直接使用的跨平台开仓代码和位置选择迁移示例。




将EA从MQL4迁移到MQL5远不止是语法更新。MQL5从根本上重构了交易管理方式:将位置和订单概念分离,打破了MQL4统一的订单池模型。理解这一架构转变是任何跨平台EA迁移的基础。

核心架构差异

MQL4使用单一订单池,挂单和市价持仓共享同一套票据系统和`OrderSelect()`机制。MQL5将两者分离:
  • 持仓(Positions):市价持仓(多/空),通过`ulong PositionGetTicket()`标识

  • 订单(Orders):挂单,通过`ulong OrderGetTicket()`标识

  • 历史记录(History):已平仓和已取消订单统一存放于历史中


  • MQL4 OrderSend到MQL5的替代方案

    MQL4中开仓使用`OrderSend()`:
    ```cpp
    // MQL4 - 原始代码
    int ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 3, stopLoss, takeProfit, "EA注释", magic, 0, Green);
    ```

    MQL5中市价持仓和挂单需要分别处理:
    ```cpp
    // MQL5 - 等价实现
    // 开立市价持仓
    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注释";
    OrderSend(request, result);
    ulong ticket = result.order;
    ```

    持仓选择模式的迁移

    MQL4的遍历选择方式:
    ```cpp
    for(int i = 0; i < OrdersTotal(); i++) {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
    if(OrderMagicNumber() == magic && OrderSymbol() == Symbol()) {
    // 处理订单
    }
    }
    }
    ```

    MQL5的持仓迭代器:
    ```cpp
    for(int i = 0; i < PositionsTotal(); i++) {
    ulong ticket = PositionGetTicket(i);
    if(PositionSelectByTicket(ticket)) {
    if(PositionGetInteger(POSITION_MAGIC) == magic && PositionGetString(POSITION_SYMBOL) == Symbol()) {
    // 处理持仓
    }
    }
    }
    ```

    风险计算的数学变换

    仓位计算公式保持一致,但获取品种信息的方式不同:

    MQL4:`MarketInfo(Symbol(), MODE_TICKVALUE)`

    MQL5:`SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE)`

    基于风险的手数计算公式:
    \[
    \text{Lots} = \frac{\text{RiskPercent} \times \text{Balance}}{100 \times \text{StopLossPoints} \times \text{TickValue}}
    \]

    其中`TickValue`需要针对报价货币进行归一化处理。对于非美元货币对,应用:
    \[
    \text{TickValue}_{\text{USD}} = \frac{\text{TickValue}_{\text{original}}}{\text{USDQuote}}
    \]

    跨平台兼容的开仓宏定义

    使用预处理器指令维护统一代码库:
    ```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
    ```

    历史记录访问迁移

    MQL4通过`OrderSelect()`配合`MODE_HISTORY`选择已平仓订单。MQL5使用`HistorySelect(startDate, endDate)`选择日期范围,然后通过`HistoryDealGetTicket()`迭代获取。

    参考来源:MQL5官方文档 - 从MQL4迁移(https://www.mql5.com/zh/docs/migration),《MetaTrader 5专家顾问编程》Andrew R. Young 著,2020年。