//+------------------------------------------------------------------+//| 辅助平仓EA.mq5 |//| Generated by AI Assistant |//| |//+------------------------------------------------------------------+#property copyright "浪人EA微信:waihuipai"#property version "1.00"// --- 外部参数 ------------------------------------------------------+input bool EnableAutoClose = true; // 启用自动平仓功能input int MagicNumber = 123456; // EA的魔术号(0=不过滤)input int Slippage = 3; // 允许滑点(点数)input int RetryDelay = 100; // 重试延迟(毫秒)input int MaxRetries = 10; // 最大重试次数// --- 全局变量 ------------------------------------------------------+struct OrderInfo{ ulong ticket; // MT5中持仓票据号为ulong类型 int type; // POSITION_TYPE_BUY / POSITION_TYPE_SELL double lots;};OrderInfo prevOrders[]; // 上一次记录的持仓列表bool autoClosing; // 防止递归自动平仓//+------------------------------------------------------------------+//| 初始化函数 |//+------------------------------------------------------------------+intOnInit(){ if(!EnableAutoClose) return(INIT_SUCCEEDED); // 保存当前符合条件的持仓 GetCurrentPositions(prevOrders); Print("自动平同类单EA已启动,Magic=", MagicNumber); return(INIT_SUCCEEDED);}//+------------------------------------------------------------------+//| 反初始化函数 |//+------------------------------------------------------------------+voidOnDeinit(constint reason){ Print("自动平同类单EA已停止,原因代码 ", reason);}//+------------------------------------------------------------------+//| Tick事件函数 |//+------------------------------------------------------------------+voidOnTick(){ if(!EnableAutoClose) return; if(autoClosing) return; // 正在自动平仓,跳过检测 // 获取当前持仓列表 OrderInfo currentPositions[]; GetCurrentPositions(currentPositions); // 查找哪个持仓被手动平仓了(存在于prevOrders但不在currentPositions中) ulong closedTicket = 0; int closedType = -1; for(int i=0; i<ArraySize(prevOrders); i++) { bool found = false; for(int j=0; j<ArraySize(currentPositions); j++) { if(prevOrders[i].ticket == currentPositions[j].ticket) { found = true; break; } } if(!found) { closedTicket = prevOrders[i].ticket; closedType = prevOrders[i].type; break; } } // 如果有持仓被手动平仓,则平掉所有同类型的持仓 if(closedTicket != 0 && (closedType == POSITION_TYPE_BUY || closedType == POSITION_TYPE_SELL)) { Print("检测到手动平仓:持仓号 ", closedTicket, ",类型 ", (closedType==POSITION_TYPE_BUY?"多单":"空单")); Print("开始自动平掉所有同类单..."); autoClosing = true; CloseAllPositionsByType(closedType); autoClosing = false; Print("自动平仓完成"); } // 更新记录,为下一次检测做准备 ArrayResize(prevOrders, ArraySize(currentPositions)); for(int i=0; i<ArraySize(currentPositions); i++) { prevOrders[i] = currentPositions[i]; }}//+------------------------------------------------------------------+//| 获取当前符合魔术号条件的所有持仓 |//+------------------------------------------------------------------+voidGetCurrentPositions(OrderInfo &positions[]){ int total = PositionsTotal(); int count = 0; ArrayResize(positions, total); for(int i=0; i<total; i++) { // 按持仓索引选择 if(PositionGetSymbol(i) == NULL) // 无效持仓则跳过 continue; ulong ticket = PositionGetInteger(POSITION_TICKET); long magic = PositionGetInteger(POSITION_MAGIC); int type = (int)PositionGetInteger(POSITION_TYPE); // 魔术号过滤 if(MagicNumber != 0 && magic != MagicNumber) continue; // 只处理市价单(多单/空单),忽略挂单持仓(挂单未成交前不是持仓) if(type != POSITION_TYPE_BUY && type != POSITION_TYPE_SELL) continue; positions[count].ticket = ticket; positions[count].type = type; positions[count].lots = PositionGetDouble(POSITION_VOLUME); count++; } ArrayResize(positions, count);}//+------------------------------------------------------------------+//| 平掉所有指定类型的持仓(仅限当前EA魔术号) |//+------------------------------------------------------------------+voidCloseAllPositionsByType(int targetType){ bool anyClosed = true; int retries = 0; while(anyClosed && retries < MaxRetries) { anyClosed = false; // 倒序循环,避免索引错乱 for(int i=PositionsTotal()-1; i>=0; i--) { if(PositionGetSymbol(i) == NULL) continue; long magic = PositionGetInteger(POSITION_MAGIC); int type = (int)PositionGetInteger(POSITION_TYPE); // 过滤魔术号 if(MagicNumber != 0 && magic != MagicNumber) continue; // 只处理目标类型 if(type != targetType) continue; string symbol = PositionGetString(POSITION_SYMBOL); double volume = PositionGetDouble(POSITION_VOLUME); ulong ticket = PositionGetInteger(POSITION_TICKET); // 尝试平仓 bool result = PositionClose(symbol, Slippage); if(result) { anyClosed = true; Print("已平仓:持仓号 ", ticket, ",品种 ", symbol, ",类型 ", (type==POSITION_TYPE_BUY?"多单":"空单")); // 平仓后持仓列表已变,break后重新从头扫描 break; } else { int err = GetLastError(); Print("平仓失败,持仓号 ", ticket, ",错误码 ", err, ",重试..."); if(RetryDelay > 0) Sleep(RetryDelay); } } retries++; if(anyClosed) retries = 0; // 有成功平仓,重置重试计数 } if(retries >= MaxRetries) Print("警告:部分持仓平仓失败,已达到最大重试次数");}//+------------------------------------------------------------------+