You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何正确平仓已开订单?(下单时无法向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

火山引擎 最新活动