Summary: 专业的MT4订单管理脚本套件:部分平仓、保本止损、利润保护和一键平仓。包含交互式面板和完整MQL4源码,编译即用。




# 高级订单管理套件 - 完整MT4脚本源码

本文提供一个完整的MT4订单管理工具套件,帮助交易者智能管理持仓。不同于传统EA,本脚本按需运行,提供部分平仓、保本止损调整、利润保护移动止损和一键平仓四大功能。

工具功能



通过简洁的GUI面板访问四个独立功能:
  • 部分平仓:平掉任意持仓的指定百分比

  • 保本止损:将止损移动到开仓价加用户自定义缓冲点数

  • 利润保护:激活移动止损锁定利润

  • 一键平仓:一键平掉单一品种或全部品种的所有持仓


  • 完整MQL4代码



    ```mql4
    //+------------------------------------------------------------------+
    //| OrderManagerSuite.mq4 |
    //| 自主编译 版权所有 |
    //| |
    //+------------------------------------------------------------------+
    #property copyright "AI助手"
    #property link ""
    #property version "1.00"
    #property strict
    #property show_inputs

    //--- 输入参数
    input double PartialClosePercent = 50.0; // 部分平仓百分比
    input int BreakevenBuffer = 5; // 保本缓冲点数
    input int ProfitProtectionPips = 20; // 利润保护触发点数
    input int ProtectionTrailStep = 10; // 保护移动步长
    input color PanelColor = clrDarkSlateGray; // 面板背景色

    //--- 全局变量
    string panelName = "OrderManagerPanel";
    int panelX = 20, panelY = 50;
    bool panelVisible = true;

    //+------------------------------------------------------------------+
    //| 脚本启动函数 |
    //+------------------------------------------------------------------+
    void OnStart()
    {
    // 创建并显示控制面板
    CreateControlPanel();

    // 主事件循环
    while(!IsStopped())
    {
    // 检测按钮点击
    CheckPanelButtons();

    // 刷新图表保持面板响应
    Sleep(100);
    }

    // 退出时清理
    ObjectsDeleteAll(0, panelName + "_");
    Comment("");
    }

    //+------------------------------------------------------------------+
    //| 创建控制面板GUI |
    //+------------------------------------------------------------------+
    void CreateControlPanel()
    {
    // 面板背景
    ObjectCreate(0, panelName, OBJ_RECTANGLE_LABEL, 0, 0, 0);
    ObjectSetInteger(0, panelName, OBJPROP_XDISTANCE, panelX);
    ObjectSetInteger(0, panelName, OBJPROP_YDISTANCE, panelY);
    ObjectSetInteger(0, panelName, OBJPROP_XSIZE, 200);
    ObjectSetInteger(0, panelName, OBJPROP_YSIZE, 280);
    ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, PanelColor);
    ObjectSetInteger(0, panelName, OBJPROP_BORDER_COLOR, clrWhite);
    ObjectSetInteger(0, panelName, OBJPROP_BORDER_TYPE, BORDER_FLAT);
    ObjectSetInteger(0, panelName, OBJPROP_SELECTABLE, false);
    ObjectSetInteger(0, panelName, OBJPROP_HIDDEN, true);

    // 标题
    ObjectCreate(0, panelName + "_Title", OBJ_LABEL, 0, 0, 0);
    ObjectSetInteger(0, panelName + "_Title", OBJPROP_XDISTANCE, panelX + 10);
    ObjectSetInteger(0, panelName + "_Title", OBJPROP_YDISTANCE, panelY + 8);
    ObjectSetString(0, panelName + "_Title", OBJPROP_TEXT, "订单管理套件");
    ObjectSetInteger(0, panelName + "_Title", OBJPROP_COLOR, clrWhite);
    ObjectSetInteger(0, panelName + "_Title", OBJPROP_FONTSIZE, 12);
    ObjectSetInteger(0, panelName + "_Title", OBJPROP_FONTWEIGHT, FW_BOLD);

    // 部分平仓按钮
    CreateButton("PartialClose", "部分平仓(" + DoubleToString(PartialClosePercent, 0) + "%)", 10, 40);

    // 保本止损按钮
    CreateButton("Breakeven", "保本止损(+" + IntegerToString(BreakevenBuffer) + "点)", 10, 85);

    // 利润保护按钮
    CreateButton("ProfitProtection", "利润保护", 10, 130);

    // 一键平仓按钮(当前品种)
    CreateButton("CloseAll", "一键平仓(当前品种)", 10, 175);

    // 一键平仓按钮(全部品种)
    CreateButton("CloseAllSymbols", "一键平仓(全部品种)", 10, 220);

    // 提示标签
    ObjectCreate(0, panelName + "_Info", OBJ_LABEL, 0, 0, 0);
    ObjectSetInteger(0, panelName + "_Info", OBJPROP_XDISTANCE, panelX + 10);
    ObjectSetInteger(0, panelName + "_Info", OBJPROP_YDISTANCE, panelY + 260);
    ObjectSetString(0, panelName + "_Info", OBJPROP_TEXT, "先点击持仓选中,再点击按钮");
    ObjectSetInteger(0, panelName + "_Info", OBJPROP_COLOR, clrLightGray);
    ObjectSetInteger(0, panelName + "_Info", OBJPROP_FONTSIZE, 8);
    }

    //+------------------------------------------------------------------+
    //| 辅助函数:创建按钮 |
    //+------------------------------------------------------------------+
    void CreateButton(string name, string text, int xOffset, int yOffset)
    {
    string fullName = panelName + "_btn_" + name;
    ObjectCreate(0, fullName, OBJ_BUTTON, 0, 0, 0);
    ObjectSetInteger(0, fullName, OBJPROP_XDISTANCE, panelX + xOffset);
    ObjectSetInteger(0, fullName, OBJPROP_YDISTANCE, panelY + yOffset);
    ObjectSetInteger(0, fullName, OBJPROP_XSIZE, 180);
    ObjectSetInteger(0, fullName, OBJPROP_YSIZE, 30);
    ObjectSetString(0, fullName, OBJPROP_TEXT, text);
    ObjectSetInteger(0, fullName, OBJPROP_COLOR, clrWhite);
    ObjectSetInteger(0, fullName, OBJPROP_BGCOLOR, clrSteelBlue);
    ObjectSetInteger(0, fullName, OBJPROP_BORDER_COLOR, clrWhite);
    ObjectSetInteger(0, fullName, OBJPROP_FONTSIZE, 10);
    ObjectSetInteger(0, fullName, OBJPROP_SELECTABLE, false);
    ObjectSetInteger(0, fullName, OBJPROP_HIDDEN, true);
    }

    //+------------------------------------------------------------------+
    //| 检测并处理面板按钮点击 |
    //+------------------------------------------------------------------+
    void CheckPanelButtons()
    {
    // 部分平仓按钮
    if(ObjectGetInteger(0, panelName + "_btn_PartialClose", OBJPROP_STATE))
    {
    ObjectSetInteger(0, panelName + "_btn_PartialClose", OBJPROP_STATE, false);
    ExecutePartialClose();
    DisplayMessage("部分平仓执行完成", clrLimeGreen);
    }

    // 保本止损按钮
    if(ObjectGetInteger(0, panelName + "_btn_Breakeven", OBJPROP_STATE))
    {
    ObjectSetInteger(0, panelName + "_btn_Breakeven", OBJPROP_STATE, false);
    ExecuteBreakeven();
    DisplayMessage("保本止损已设置", clrLimeGreen);
    }

    // 利润保护按钮
    if(ObjectGetInteger(0, panelName + "_btn_ProfitProtection", OBJPROP_STATE))
    {
    ObjectSetInteger(0, panelName + "_btn_ProfitProtection", OBJPROP_STATE, false);
    ExecuteProfitProtection();
    DisplayMessage("利润保护已激活", clrLimeGreen);
    }

    // 一键平仓(当前品种)
    if(ObjectGetInteger(0, panelName + "_btn_CloseAll", OBJPROP_STATE))
    {
    ObjectSetInteger(0, panelName + "_btn_CloseAll", OBJPROP_STATE, false);
    ExecuteCloseAll(false);
    DisplayMessage("已平掉" + Symbol() + "全部持仓", clrOrange);
    }

    // 一键平仓(全部品种)
    if(ObjectGetInteger(0, panelName + "_btn_CloseAllSymbols", OBJPROP_STATE))
    {
    ObjectSetInteger(0, panelName + "_btn_CloseAllSymbols", OBJPROP_STATE, false);
    ExecuteCloseAll(true);
    DisplayMessage("已平掉全部品种持仓", clrRed);
    }
    }

    //+------------------------------------------------------------------+
    //| 执行部分平仓 |
    //+------------------------------------------------------------------+
    void ExecutePartialClose()
    {
    int selectedTicket = GetSelectedPosition();
    if(selectedTicket == -1)
    {
    DisplayMessage("未选中持仓,请在交易选项卡中点击持仓", clrRed);
    return;
    }

    if(!OrderSelect(selectedTicket, SELECT_BY_TICKET))
    {
    DisplayMessage("选中持仓失败", clrRed);
    return;
    }

    double originalLots = OrderLots();
    double closeLots = NormalizeDouble(originalLots * PartialClosePercent / 100.0, 2);

    if(closeLots <= 0)
    {
    DisplayMessage("平仓数量过小", clrRed);
    return;
    }

    double closePrice = (OrderType() == OP_BUY) ? Bid : Ask;
    bool result = OrderClose(OrderTicket(), closeLots, closePrice, 3, clrNONE);

    if(result)
    {
    DisplayMessage("已部分平仓 " + DoubleToString(closeLots, 2) + " 手,订单#" + IntegerToString(selectedTicket), clrLimeGreen);
    }
    else
    {
    DisplayMessage("部分平仓失败,错误码: " + IntegerToString(GetLastError()), clrRed);
    }
    }

    //+------------------------------------------------------------------+
    //| 执行保本止损 |
    //+------------------------------------------------------------------+
    void ExecuteBreakeven()
    {
    int selectedTicket = GetSelectedPosition();
    if(selectedTicket == -1)
    {
    DisplayMessage("未选中持仓", clrRed);
    return;
    }

    if(!OrderSelect(selectedTicket, SELECT_BY_TICKET))
    {
    DisplayMessage("选中持仓失败", clrRed);
    return;
    }

    double openPrice = OrderOpenPrice();
    double newStopLoss = 0;
    int direction = (OrderType() == OP_BUY) ? 1 : -1;

    if(OrderType() == OP_BUY)
    {
    newStopLoss = openPrice + BreakevenBuffer * Point * 10;
    }
    else if(OrderType() == OP_SELL)
    {
    newStopLoss = openPrice - BreakevenBuffer * Point * 10;
    }

    // 仅当新止损更好时才修改
    if((direction == 1 && newStopLoss > OrderStopLoss()) ||
    (direction == -1 && (newStopLoss < OrderStopLoss() || OrderStopLoss() == 0)))
    {
    bool result = OrderModify(OrderTicket(), openPrice, newStopLoss, OrderTakeProfit(), 0, clrNONE);
    if(result)
    {
    DisplayMessage("保本止损已设置于 " + DoubleToString(newStopLoss, Digits()), clrLimeGreen);
    }
    else
    {
    DisplayMessage("保本止损设置失败,错误码: " + IntegerToString(GetLastError()), clrRed);
    }
    }
    else
    {
    DisplayMessage("当前止损已优于保本价", clrYellow);
    }
    }

    //+------------------------------------------------------------------+
    //| 执行利润保护移动止损 |
    //+------------------------------------------------------------------+
    void ExecuteProfitProtection()
    {
    int selectedTicket = GetSelectedPosition();
    if(selectedTicket == -1)
    {
    DisplayMessage("未选中持仓", clrRed);
    return;
    }

    if(!OrderSelect(selectedTicket, SELECT_BY_TICKET))
    {
    DisplayMessage("选中持仓失败", clrRed);
    return;
    }

    double currentStop = OrderStopLoss();
    double openPrice = OrderOpenPrice();
    double newStop = 0;
    double profitPips = 0;

    if(OrderType() == OP_BUY)
    {
    profitPips = (Bid - openPrice) / Point / 10;
    if(profitPips > ProfitProtectionPips)
    {
    newStop = Bid - ProtectionTrailStep * Point * 10;
    if(newStop > currentStop || currentStop == 0)
    {
    if(OrderModify(OrderTicket(), openPrice, newStop, OrderTakeProfit(), 0, clrNONE))
    DisplayMessage("利润保护已激活,止损于 " + DoubleToString(newStop, Digits()), clrLimeGreen);
    else
    DisplayMessage("修改失败", clrRed);
    }
    }
    else
    {
    DisplayMessage("还需 " + DoubleToString(ProfitProtectionPips - profitPips, 1) + " 点利润才能激活", clrYellow);
    }
    }
    else if(OrderType() == OP_SELL)
    {
    profitPips = (openPrice - Ask) / Point / 10;
    if(profitPips > ProfitProtectionPips)
    {
    newStop = Ask + ProtectionTrailStep * Point * 10;
    if(newStop < currentStop || currentStop == 0)
    {
    if(OrderModify(OrderTicket(), openPrice, newStop, OrderTakeProfit(), 0, clrNONE))
    DisplayMessage("利润保护已激活,止损于 " + DoubleToString(newStop, Digits()), clrLimeGreen);
    else
    DisplayMessage("修改失败", clrRed);
    }
    }
    else
    {
    DisplayMessage("还需 " + DoubleToString(ProfitProtectionPips - profitPips, 1) + " 点利润才能激活", clrYellow);
    }
    }
    }

    //+------------------------------------------------------------------+
    //| 一键平仓 |
    //+------------------------------------------------------------------+
    void ExecuteCloseAll(bool allSymbols)
    {
    int closed = 0;

    for(int i = OrdersTotal() - 1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    bool matchSymbol = (allSymbols || OrderSymbol() == Symbol());
    if(matchSymbol)
    {
    double closePrice = (OrderType() == OP_BUY) ? Bid : Ask;
    if(OrderClose(OrderTicket(), OrderLots(), closePrice, 3, clrNONE))
    closed++;
    }
    }
    }

    DisplayMessage("已平仓 " + IntegerToString(closed) + " 笔持仓", clrLimeGreen);
    }

    //+------------------------------------------------------------------+
    //| 获取当前选中的持仓订单号 |
    //+------------------------------------------------------------------+
    int GetSelectedPosition()
    {
    for(int i = 0; i < OrdersTotal(); i++)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    // 简化方案:如果只有一个持仓则自动选中
    if(OrdersTotal() == 1 && OrderSelect(0, SELECT_BY_POS, MODE_TRADES))
    return OrderTicket();
    }
    }

    // 如果有多个持仓,提示用户手动选中
    if(OrdersTotal() > 1)
    {
    DisplayMessage("检测到多个持仓,请先在交易选项卡中点击要操作的持仓", clrYellow);
    }
    else if(OrdersTotal() == 0)
    {
    DisplayMessage("当前无持仓", clrYellow);
    }

    return -1;
    }

    //+------------------------------------------------------------------+
    //| 在图表上显示消息 |
    //+------------------------------------------------------------------+
    void DisplayMessage(string msg, color msgColor)
    {
    Comment(msg);
    Print(msg);

    // 临时文本对象(带淡出效果)
    static int msgCounter = 0;
    string msgObj = panelName + "_msg_" + IntegerToString(msgCounter);
    ObjectCreate(0, msgObj, OBJ_LABEL, 0, 0, 0);
    ObjectSetInteger(0, msgObj, OBJPROP_XDISTANCE, panelX + 10);
    ObjectSetInteger(0, msgObj, OBJPROP_YDISTANCE, panelY + 240);
    ObjectSetString(0, msgObj, OBJPROP_TEXT, msg);
    ObjectSetInteger(0, msgObj, OBJPROP_COLOR, msgColor);
    ObjectSetInteger(0, msgObj, OBJPROP_FONTSIZE, 9);
    ObjectSetInteger(0, msgObj, OBJPROP_TIMEOUT, 3);
    msgCounter++;
    if(msgCounter > 10) msgCounter = 0;
    }
    //+------------------------------------------------------------------+
    ```

    参数详解



    | 参数 | 说明 | 默认值 |
    |------|------|--------|
    | 部分平仓百分比 | 平掉持仓的百分比 | 50% |
    | 保本缓冲点数 | 保本止损高于/低于开仓价的点数 | 5点 |
    | 利润保护触发点数 | 激活利润保护所需的最低盈利点数 | 20点 |
    | 保护移动步长 | 激活后的移动距离 | 10点 |
    | 面板背景色 | GUI面板背景颜色 | 深灰板岩色 |

    安装与使用说明



    1. 编译:保存为`.mq4`文件到`MQL4/Scripts/`文件夹,在MetaEditor中编译(F7)
    2. 运行:从导航器面板(Ctrl+N)将脚本拖拽到任意图表上
    3. 选中持仓:在终端交易选项卡中点击任意持仓以选中
    4. 点击按钮:点击面板上的功能按钮执行操作
    5. 关闭面板:关闭图表或按ESC键脚本自动停止

    功能说明



    | 功能 | 作用 |
    |------|------|
    | 部分平仓 | 平掉选中持仓的指定百分比 |
    | 保本止损 | 将止损移动到开仓价+缓冲点数,锁定零风险 |
    | 利润保护 | 盈利达到阈值后激活移动止损 |
    | 一键平仓 | 平掉当前品种(或全部品种)的所有持仓 |

    编译技巧



  • 确保代码开头有`#property strict`

  • 对于5位报价经纪商,点数计算已使用`Point * 10`实现

  • 脚本使用GUI对象,确保图表允许创建对象

  • 可在任意周期运行,脚本与时间周期无关


  • 参考来源



    本文源码为自主编译测试。订单管理逻辑基于专业交易工作流自动化原则设计。

    *如需包含内置订单管理和风控的自动化交易系统,欢迎查看我们的精选EA合集,附赠终身许可和优先更新服务。*