# 高级订单管理套件 - 完整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键脚本自动停止
功能说明
| 功能 | 作用 |
|------|------|
| 部分平仓 | 平掉选中持仓的指定百分比 |
| 保本止损 | 将止损移动到开仓价+缓冲点数,锁定零风险 |
| 利润保护 | 盈利达到阈值后激活移动止损 |
| 一键平仓 | 平掉当前品种(或全部品种)的所有持仓 |
编译技巧
参考来源
本文源码为自主编译测试。订单管理逻辑基于专业交易工作流自动化原则设计。
*如需包含内置订单管理和风控的自动化交易系统,欢迎查看我们的精选EA合集,附赠终身许可和优先更新服务。*