如何正确平仓已开订单?(下单时无法向position参数传入订单编号)
解决MT5无需手动复制订单号即可平仓的问题
我明白你现在的痛点——每次开单后还要手动复制订单号粘贴到平仓函数里,确实太繁琐了。这里有两种靠谱的自动化方案,帮你摆脱这个重复操作:
方法一:开单后直接保存订单号,平仓时复用
你可以在开单成功后把订单号(Ticket Number)存储到全局变量、本地文件甚至数据库里,平仓时直接调用这个值就行。修改后的代码示例如下:
import MetaTrader5 as mt5 if not mt5.initialize(): print("initialize() failed, error code =", mt5.last_error()) quit() symbol = "EURUSD" lot = 0.1 deviation = 20 # 全局变量存储当前持仓订单号 current_ticket = None def buy(): global current_ticket # 先获取最新报价,避免开单时价格无效 tick = mt5.symbol_info_tick(symbol) if tick is None: print(f"获取{symbol}报价失败,错误码:{mt5.last_error()}") return request = { "action": mt5.TRADE_ACTION_DEAL, "symbol": symbol, "volume": lot, "type": mt5.ORDER_TYPE_BUY, "price": tick.ask, "position": 0, # 严格按官方要求设为0 "deviation": deviation, "magic": 234000, "comment": "python script open", "type_time": mt5.ORDER_TIME_GTC, "type_filling": mt5.ORDER_FILLING_IOC, } result = mt5.order_send(request) if result.retcode == mt5.TRADE_RETCODE_DONE: print(f"开单成功,订单号:{result.order}") current_ticket = result.order else: print(f"开单失败,错误码:{result.retcode},详情:{mt5.last_error()}") def close(): global current_ticket if current_ticket is None: print("没有可平仓的有效订单号") return tick = mt5.symbol_info_tick(symbol) if tick is None: print(f"获取{symbol}报价失败,错误码:{mt5.last_error()}") return close_request = { "action": mt5.TRADE_ACTION_DEAL, "symbol": symbol, "volume": lot, "type": mt5.ORDER_TYPE_SELL, "position": current_ticket, # 直接复用保存的订单号 "price": tick.bid, "deviation": deviation, "magic": 234000, # 建议和开单的magic值保持一致,方便策略管理 "comment": "python script close", "type_time": mt5.ORDER_TIME_GTC, "type_filling": mt5.ORDER_FILLING_IOC, } result = mt5.order_send(close_request) if result.retcode == mt5.TRADE_RETCODE_DONE: print(f"平仓成功,订单号:{current_ticket}") current_ticket = None # 平仓后清空变量 else: print(f"平仓失败,错误码:{result.retcode},详情:{mt5.last_error()}") # 执行流程:先开单再平仓 buy() # 可选:添加1秒延迟,确保订单已在服务器端成交 # import time # time.sleep(1) close() mt5.shutdown()
关键点说明:
- 用全局变量
current_ticket实时存储开单成功后的订单号 - 增加了报价获取的错误判断,避免因无报价导致交易失败
- 平仓前先校验订单号是否有效,减少无效请求
方法二:通过Magic Number和Symbol查找持仓订单
如果担心脚本重启后全局变量失效,或者需要批量平仓同一策略的持仓,可以通过mt5.positions_get()函数直接查找符合条件的持仓,完全不用依赖预先保存的订单号:
import MetaTrader5 as mt5 if not mt5.initialize(): print("initialize() failed, error code =", mt5.last_error()) quit() symbol = "EURUSD" lot = 0.1 deviation = 20 MAGIC_NUMBER = 234000 # 你的策略专属magic值 def buy(): tick = mt5.symbol_info_tick(symbol) if tick is None: print(f"获取{symbol}报价失败,错误码:{mt5.last_error()}") return request = { "action": mt5.TRADE_ACTION_DEAL, "symbol": symbol, "volume": lot, "type": mt5.ORDER_TYPE_BUY, "price": tick.ask, "position": 0, "deviation": deviation, "magic": MAGIC_NUMBER, "comment": "python script open", "type_time": mt5.ORDER_TIME_GTC, "type_filling": mt5.ORDER_FILLING_IOC, } result = mt5.order_send(request) if result.retcode == mt5.TRADE_RETCODE_DONE: print(f"开单成功,订单号:{result.order}") else: print(f"开单失败,错误码:{result.retcode},详情:{mt5.last_error()}") def close_by_magic(): # 查找指定品种的所有持仓 positions = mt5.positions_get(symbol=symbol) if positions is None: print(f"未找到{symbol}的持仓,错误码:{mt5.last_error()}") return if len(positions) == 0: print(f"{symbol}当前无持仓") return # 遍历持仓,找到属于当前策略的订单 for pos in positions: if pos.magic == MAGIC_NUMBER: tick = mt5.symbol_info_tick(symbol) if tick is None: print(f"获取{symbol}报价失败,错误码:{mt5.last_error()}") continue close_request = { "action": mt5.TRADE_ACTION_DEAL, "symbol": symbol, "volume": pos.volume, # 用持仓的实际仓位,避免手数不匹配 "type": mt5.ORDER_TYPE_SELL, "position": pos.ticket, "price": tick.bid, "deviation": deviation, "magic": MAGIC_NUMBER, "comment": "python script close by magic", "type_time": mt5.ORDER_TIME_GTC, "type_filling": mt5.ORDER_FILLING_IOC, } result = mt5.order_send(close_request) if result.retcode == mt5.TRADE_RETCODE_DONE: print(f"平仓成功,订单号:{pos.ticket}") else: print(f"平仓失败,订单号:{pos.ticket},错误码:{result.retcode}") else: print(f"跳过非当前策略的持仓,订单号:{pos.ticket}") # 执行流程 buy() # time.sleep(1) # 可选延迟,确保订单成交 close_by_magic() mt5.shutdown()
优势说明:
- 无需保存订单号,通过策略专属的Magic Number精准定位持仓
- 支持批量平仓同一策略下的多个持仓
- 脚本重启后依然能正常找到符合条件的持仓
补充:为什么不能预先设置订单号?
MT5的订单号是由服务器端自动生成的唯一标识,属于系统分配的序列值,无法手动预先指定。所以你只能在开单成功后获取这个编号,或者通过Magic Number、品种等条件反向查找持仓。
内容的提问来源于stack exchange,提问作者edward




