MT4程序在MT5上运行:MT4的交易函数移植到MT5上运行

本文介绍了将MT4中的交易函数移植到MT5平台的过程,包括了交易函数的区别、参数调整、示例代码以及订单执行中的检查机制。作者强调了从MQL4到MQL5迁移的必要性,以支持跨平台EA的运行和提升开发者效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MT4移值交易函数到MT5上意义

  • 可以开发跨平台EA,开发一个EA,则MT4与MT5上都可运行
  • 让很多优秀策略思想的MQL4语言的EA可移值到到MT5上运行
  • 加深对MQL4语言与MQL5语言交易机制的理解,提升快发能力

MT4交易函数与MT5交易函数的区别

  • MT4的交易函数参数为基本变量,而MT5的为结构体,两者无法兼容
  • MT4的交易函数缺少很多参数检查机制与错误返回,

MT4的交易函数移植到MT5上实现代码如下

  • OrderSendMQL4 发送订单函数的实现,带MQL4后缀避免与MT5中OrderSend同名而无法实现导出库功能
  • OrderClose 仓位关闭函数的实现
  • OrderDelete 删除挂单函数的实现
  • FillingCheck 订单订单填充检查,为满足MT5交易机制为设置,被OrderSendMQL4调用
  • CheckStopLoss_Takeprofit 检查止损和止盈的正确性,被交易函数调用
  • ExpirationCheck 检查挂单的到期类型,被交易函数调用

// MT4交易函数常量定义
#define OP_BUY                 0  //Buy 
#define OP_SELL                1  //Sell 
#define OP_BUYLIMIT            2  //Pending order of BUY LIMIT type 
#define OP_SELLLIMIT           3  //Pending order of SELL LIMIT type 
#define OP_BUYSTOP             4  //Pending order of BUY STOP type 
#define OP_SELLSTOP            5  //Pending order of SELL STOP type 
//+------------------------------------------------------------------+
//| MT4交易函数原型在MT5上的实现                                     |
//+------------------------------------------------------------------+
int OrderSendMQL4(string symbol,             // symbol 
        int      cmd,                        // operation 
        double   volume,                     // volume 
        double   price,                      // price 
        int      slippage,                   // slippage 
        double   sl,                         // stop loss 
        double   tp,                         // take profit 
        string   comment=NULL,               // comment 
        int      magic=0,                    // magic number 
        datetime expiration=0,               // pending order expiration 
        color    arrow_color=clrNONE) export // color 
{
    MqlTradeRequest request = {};
    MqlTradeResult  result  = {};
    request.action = TRADE_ACTION_DEAL;     //
    if (cmd == OP_BUY)
        request.type = ORDER_TYPE_BUY;
    if (cmd == OP_SELL)
        request.type = ORDER_TYPE_SELL;
    if (cmd == OP_BUYLIMIT)
        request.type = ORDER_TYPE_BUY_LIMIT;
    if (cmd == OP_SELLLIMIT)
        request.type = ORDER_TYPE_SELL_LIMIT;
    if (cmd == OP_BUYSTOP)
        request.type = ORDER_TYPE_BUY_STOP;
    if (cmd == OP_SELLSTOP)
        request.type = ORDER_TYPE_SELL_STOP;
    request.magic  = magic;                 //
    request.symbol = symbol;                //
    request.volume = volume;                //
    request.sl = sl;                        // Stop Loss
    request.tp = tp;                        // Take Profit   
    request.price = price;                  //
    request.deviation = slippage;           //
    request.comment = comment;              //
    request.expiration = expiration;        //
    // 检查订单填充
    if ( !FillingCheck(symbol, request, result) ) return (-1);
    // 检查止损止损盈
    if ( !CheckStopLoss_Takeprofit(request.type, request.price, request.sl, request.tp, symbol) ) return (0);
    if ( OrderSend(request, result) ) 
        return ( (int)result.deal );
    else
        return (-1);
}
//+------------------------------------------------------------------+
//| 关闭仓位函数的实现                                               |
//+------------------------------------------------------------------+
bool OrderClose(long ticket, double lots, double price, int slippage, color arrow_color=clrNONE) export
{
    //-- 声明交易请求和交易请求结果
    MqlTradeRequest request;
    MqlTradeResult  result;
    //--- 归零请求和结果值
    ZeroMemory(request);
    ZeroMemory(result);
    // 无法选择仓位订单,或许订单不存在
    if (PositionSelectByTicket(ticket)) return (false);
    ENUM_POSITION_TYPE pos_type = (ENUM_POSITION_TYPE)::PositionGetInteger(POSITION_TYPE);

    //--- 根据持仓类型设置价格和订单类型 
    if (pos_type == POSITION_TYPE_BUY)
    {
        request.price = SymbolInfoDouble(request.symbol, SYMBOL_BID);
        request.type  = ORDER_TYPE_SELL;
    }
    else if (pos_type == POSITION_TYPE_SELL)
    {
        request.price = SymbolInfoDouble(request.symbol, SYMBOL_ASK);
        request.type  = ORDER_TYPE_BUY;
    }

    double volume     = ::PositionGetDouble(POSITION_VOLUME); // 成交量
    request.action    = TRADE_ACTION_DEAL;                    // 交易操作类型
    request.position  = ticket;                               // 仓位ID
    request.symbol    = ::PositionGetString(POSITION_SYMBOL); // 交易品种 
    request.volume    = volume<=lots ? volume: lots;          // 持仓交易量
    request.deviation = slippage;                             // 允许价格偏差
    //
    if ( !FillingCheck(request.symbol, request, result) ) return (false);
    //--- 发送请求
    if ( !OrderSend(request, result) )
    {
        PrintFormat("OrderSend error %d", GetLastError());
        PrintFormat("retcode=%u  deal=%I64u  order=%I64u", result.retcode, result.deal, result.order);
        return (false);
    } // 如果不能发送请求,输出错误代码
    return (true);
}
//+------------------------------------------------------------------+
//| 删除挂单函数的实现                                               |
//+------------------------------------------------------------------+
bool OrderDelete(long ticket, color arrow_color=clrNONE) export
{
    MqlTradeRequest request;
    MqlTradeResult  result;
    //--- 归零请求和结果值
    ZeroMemory(request);
    ZeroMemory(result);
    // 如果挂单不存在,直接返回
    if ( !OrderSelect(ticket) ) return (false);
    //
    request.action = TRADE_ACTION_REMOVE;
    request.order  = ticket;
    if ( !OrderSend(request, result) )
    {
        PrintFormat( "OrderSend error %d", GetLastError() );
        PrintFormat( "retcode=%u  deal=%I64u  order=%I64u", result.retcode, result.deal, result.order);
        return (false);
    }
    //
    return (true);
}
//+------------------------------------------------------------------+
//| 订单填充的检查,无此函数检查,MT5发送订单可能会报错              |
//+------------------------------------------------------------------+
bool FillingCheck(const string symbol, MqlTradeRequest &request, MqlTradeResult &result)
{
    ENUM_ORDER_TYPE_FILLING type_filling = ORDER_FILLING_FOK;
    //--- get execution mode of orders by symbol
    ENUM_SYMBOL_TRADE_EXECUTION exec=(ENUM_SYMBOL_TRADE_EXECUTION)SymbolInfoInteger(symbol,SYMBOL_TRADE_EXEMODE);
    //--- check execution mode
    if(exec==SYMBOL_TRADE_EXECUTION_REQUEST || exec==SYMBOL_TRADE_EXECUTION_INSTANT)
    {
        //--- neccessary filling type will be placed automatically
        return(true);
    }
    //--- get possible filling policy types by symbol
    uint filling=(uint)SymbolInfoInteger(symbol,SYMBOL_FILLING_MODE);
    //--- check execution mode again
    if(exec==SYMBOL_TRADE_EXECUTION_MARKET)
    {
        //--- for the MARKET execution mode
        //--- analyze order
        if(request.action!=TRADE_ACTION_PENDING)
        {
            //--- in case of instant execution order
            //--- if the required filling policy is supported, add it to the request
            if((filling&SYMBOL_FILLING_FOK)==SYMBOL_FILLING_FOK)
            {
                type_filling=ORDER_FILLING_FOK;
                request.type_filling=type_filling;
                return(true);
            }
            if((filling&SYMBOL_FILLING_IOC)==SYMBOL_FILLING_IOC)
            {
                type_filling=ORDER_FILLING_IOC;
                request.type_filling=type_filling;
                return(true);
            }
            //--- wrong filling policy, set error code
            result.retcode=TRADE_RETCODE_INVALID_FILL;
            return(false);
        }
        return(true);
    }
    //--- EXCHANGE execution mode
    switch(type_filling)
    {
        case ORDER_FILLING_FOK:
            //--- analyze order
            if(request.action==TRADE_ACTION_PENDING)
            {
                //--- in case of pending order
                //--- add the expiration mode to the request
                if(!ExpirationCheck(symbol, request))
                    request.type_time=ORDER_TIME_DAY;
                //--- stop order?
                if(request.type==ORDER_TYPE_BUY_STOP || request.type==ORDER_TYPE_SELL_STOP ||
                        request.type==ORDER_TYPE_BUY_LIMIT || request.type==ORDER_TYPE_SELL_LIMIT)
                {
                    //--- in case of stop order
                    //--- add the corresponding filling policy to the request
                    request.type_filling=ORDER_FILLING_RETURN;
                    return(true);
                }
            }
            //--- in case of limit order or instant execution order
            //--- if the required filling policy is supported, add it to the request
            if((filling&SYMBOL_FILLING_FOK)==SYMBOL_FILLING_FOK)
            {
                request.type_filling=type_filling;
                return(true);
            }
            //--- wrong filling policy, set error code
            result.retcode=TRADE_RETCODE_INVALID_FILL;
            return(false);
        case ORDER_FILLING_IOC:
            //--- analyze order
            if(request.action==TRADE_ACTION_PENDING)
            {
                //--- in case of pending order
                //--- add the expiration mode to the request
                if(!ExpirationCheck(symbol, request))
                    request.type_time=ORDER_TIME_DAY;
                //--- stop order?
                if(request.type==ORDER_TYPE_BUY_STOP || request.type==ORDER_TYPE_SELL_STOP ||
                        request.type==ORDER_TYPE_BUY_LIMIT || request.type==ORDER_TYPE_SELL_LIMIT)
                {
                    //--- in case of stop order
                    //--- add the corresponding filling policy to the request
                    request.type_filling=ORDER_FILLING_RETURN;
                    return(true);
                }
            }
            //--- in case of limit order or instant execution order
            //--- if the required filling policy is supported, add it to the request
            if((filling&SYMBOL_FILLING_IOC)==SYMBOL_FILLING_IOC)
            {
                request.type_filling=type_filling;
                return(true);
            }
            //--- wrong filling policy, set error code
            result.retcode=TRADE_RETCODE_INVALID_FILL;
            return(false);
        case ORDER_FILLING_RETURN:
            //--- add filling policy to the request
            request.type_filling=type_filling;
            return(true);
    }
    //--- unknown execution mode, set error code
    result.retcode=TRADE_RETCODE_ERROR;
    return(false);
}
//+------------------------------------------------------------------+
//| 检查止损和止盈的正确性                                           |
//+------------------------------------------------------------------+
bool CheckStopLoss_Takeprofit(ENUM_ORDER_TYPE type, double price, double SL, double TP, string symbol=NULL) export
{
    if (symbol == NULL) symbol = _Symbol;
    //--- get the SYMBOL_TRADE_STOPS_LEVEL level
    int stops_level=(int)SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL);
    if(stops_level!=0)
    {
        PrintFormat("SYMBOL_TRADE_STOPS_LEVEL=%d: StopLoss and TakeProfit must"+
                " not be nearer than %d points from the closing price",stops_level,stops_level);
    }
    //---
    bool SL_check=false,TP_check=false;
    double bid = ::SymbolInfoDouble(symbol, SYMBOL_BID);
    double ask = ::SymbolInfoDouble(symbol, SYMBOL_ASK);
    double point = ::SymbolInfoDouble(symbol, SYMBOL_POINT);
    //--- check the order type
    switch (type)
    {
        //--- Buy operation
        case  ORDER_TYPE_BUY:
            {
                //--- check the StopLoss
                if (SL != 0)
                    SL_check=(bid-SL>stops_level*point);
                else
                    SL_check = true;
                if(!SL_check)
                    PrintFormat("For order %s   StopLoss=%.5f must be less than %.5f"+
                            " (Bid=%.5f - SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                            EnumToString(type),SL,bid-stops_level*point,bid,stops_level);
                //--- check the TakeProfit
                if (TP != 0)
                    TP_check = (TP-bid>stops_level*point);
                else
                    TP_check = true;
                if(!TP_check)
                    PrintFormat("For order %s   TakeProfit=%.5f must be greater than %.5f"+
                            " (Bid=%.5f + SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                            EnumToString(type),TP,bid+stops_level*point,bid,stops_level);
                //--- return the result of checking
                return(SL_check&&TP_check);
            }
            //--- Sell operation
        case  ORDER_TYPE_SELL:
            {
                //--- check the StopLoss
                if (SL != 0)
                    SL_check=(SL-SymbolInfoDouble(symbol,SYMBOL_ASK)>stops_level*point);
                else
                    SL_check = true;
                if(!SL_check)
                    PrintFormat("For order %s   StopLoss=%.5f must be greater than %.5f"+
                            " (Ask=%.5f + SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                            EnumToString(type),SL,ask+stops_level*point,ask,stops_level);
                //--- check the TakeProfit
                if (TP != 0)
                    TP_check=(ask-TP>stops_level*point);
                else
                    TP_check = true;
                if(!TP_check)
                    PrintFormat("For order %s   TakeProfit=%.5f must be less than %.5f"+
                            " (Ask=%.5f - SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                            EnumToString(type),TP,ask-stops_level*point,ask,stops_level);
                //--- return the result of checking
                return(TP_check&&SL_check);
            }
            break;
            //--- BuyLimit pending order
        case  ORDER_TYPE_BUY_LIMIT:
            {
                //--- check the StopLoss
                if (SL != 0)
                    SL_check=((price-SL)>stops_level*point);
                else
                    SL_check = true;
                if(!SL_check)
                    PrintFormat("For order %s   StopLoss=%.5f must be less than %.5f"+
                            " (Open-StopLoss=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                            EnumToString(type),SL,price-stops_level*point,(int)((price-SL)/point),stops_level);
                //--- check the TakeProfit
                if (TP != 0)
                    TP_check=((TP-price)>stops_level*point);
                else
                    TP_check = true;
                if(!TP_check)
                    PrintFormat("For order %s   TakeProfit=%.5f must be greater than %.5f"+
                            " (TakeProfit-Open=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                            EnumToString(type),TP,price+stops_level*point,(int)((TP-price)/point),stops_level);
                //--- return the result of checking
                return(SL_check&&TP_check);
            }
            //--- SellLimit pending order
        case  ORDER_TYPE_SELL_LIMIT:
            {
                //--- check the StopLoss
                if (SL != 0)
                    SL_check=((SL-price)>stops_level*point);
                else
                    SL_check = true;
                if(!SL_check)
                    PrintFormat("For order %s   StopLoss=%.5f must be greater than %.5f"+
                            " (StopLoss-Open=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                            EnumToString(type),SL,price+stops_level*point,(int)((SL-price)/point),stops_level);
                //--- check the TakeProfit
                if (TP!=0)
                    TP_check=((price-TP)>stops_level*point);
                else
                    TP_check = true;
                if(!TP_check)
                    PrintFormat("For order %s   TakeProfit=%.5f must be less than %.5f"+
                            " (Open-TakeProfit=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                            EnumToString(type),TP,price-stops_level*point,(int)((price-TP)/point),stops_level);
                //--- return the result of checking
                return(TP_check&&SL_check);
            }
            break;
            //--- BuyStop pending order
        case  ORDER_TYPE_BUY_STOP:
            {
                //--- check the StopLoss
                if (SL != 0)
                    SL_check=((price-SL)>stops_level*point);
                else
                    SL_check = true;
                if(!SL_check)
                    PrintFormat("For order %s   StopLoss=%.5f must be less than %.5f"+
                            " (Open-StopLoss=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                            EnumToString(type),SL,price-stops_level*point,(int)((price-SL)/point),stops_level);
                //--- check the TakeProfit
                if (TP!=0)
                    TP_check=((TP-price)>stops_level*point);
                else
                    TP_check = true;
                if(!TP_check)
                    PrintFormat("For order %s   TakeProfit=%.5f must be greater than %.5f"+
                            " (TakeProfit-Open=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                            EnumToString(type),TP,price-stops_level*point,(int)((TP-price)/point),stops_level);
                //--- return the result of checking
                return(SL_check&&TP_check);
            }
            //--- SellStop pending order
        case  ORDER_TYPE_SELL_STOP:
            {
                //--- check the StopLoss
                if (SL != 0)
                    SL_check=((SL-price)>stops_level*point);
                else
                    SL_check = true;
                if(!SL_check)
                    PrintFormat("For order %s   StopLoss=%.5f must be greater than %.5f"+
                            " (StopLoss-Open=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                            EnumToString(type),SL,price+stops_level*point,(int)((SL-price)/point),stops_level);
                //--- check the TakeProfit
                if (TP != 0)
                    TP_check=((price-TP)>stops_level*point);
                else
                    TP_check = true;
                if(!TP_check)
                    PrintFormat("For order %s   TakeProfit=%.5f must be less than %.5f"+
                            " (Open-TakeProfit=%d points ==> SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                            EnumToString(type),TP,price-stops_level*point,(int)((price-TP)/point),stops_level);
                //--- return the result of checking
                return(TP_check&&SL_check);
            }
            break;
    }

    //---
    return false;
}
//+------------------------------------------------------------------+
//| 检查挂起订单的到期类型                                           |
//+------------------------------------------------------------------+
bool ExpirationCheck(const string symbol, MqlTradeRequest &request) export
{
    //--- check symbol
    string symbol_name=(symbol==NULL) ? _Symbol : symbol;
    //--- get flags
    long tmp_long;
    int  flags=0;
    if(SymbolInfoInteger(symbol_name,SYMBOL_EXPIRATION_MODE,tmp_long))
        flags=(int)tmp_long;
    //--- check type
    switch(request.type_time)
    {
        case ORDER_TIME_GTC:
            if((flags&SYMBOL_EXPIRATION_GTC)!=0)
                return(true);
            break;
        case ORDER_TIME_DAY:
            if((flags&SYMBOL_EXPIRATION_DAY)!=0)
                return(true);
            break;
        case ORDER_TIME_SPECIFIED:
            if((flags&SYMBOL_EXPIRATION_SPECIFIED)!=0)
                return(true);
            break;
        case ORDER_TIME_SPECIFIED_DAY:
            if((flags&SYMBOL_EXPIRATION_SPECIFIED_DAY)!=0)
                return(true);
            break;
        default:
            Print(__FUNCTION__+": Unknown expiration type");
    }
    //--- failed
    return(false);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迈达量化

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值