You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MT5 Python下单报错Invalid stops问题排查与解决

MT5 Python接口下单报错"Invalid stops"问题排查与修复

问题场景

在Windows 11系统下使用Python 3.7对接RoboMarkets的MT5接口,调用自定义卖单函数时无法成功下单,返回retcode=10016且提示Invalid stops,同时出现symbol_info_tick() failed, error code = (1, 'Success')的异常提示。

自定义下单函数代码

def open_trade_sell2(action, symbol, lot, tp, deviation, ea_magic_number,comment):
    '''https://www.mql5.com/en/docs/integration/python_metatrader5/mt5ordersend_py
    '''
    # prepare the buy request structure
    symbol_info = get_info(symbol)
    print("symbol info",symbol_info)

    #symbol_info_tick_dict = mt5.symbol_info_tick(symbol)._asdict()
    #for prop in symbol_info_tick_dict:
    #        print("  {}={}".format(prop, symbol_info_tick_dict[prop]))
   
    if not mt5.initialize():
        print("initialize() failed, error code =",mt5.last_error())
        quit()
    # display the last GBPUSD tick
    lasttick=mt5.symbol_info_tick(symbol)
    print(lasttick)

    if action == 'buy':
        trade_type = mt5.ORDER_TYPE_BUY
        price = mt5.symbol_info_tick(symbol).ask
        pass
    elif action =='sell':
        trade_type = mt5.ORDER_TYPE_SELL
        
        price = mt5.symbol_info_tick(symbol).bid
        print(price)
        pass
    #point = mt5.symbol_info(symbol).point
    if tp< price:
        print("el precio mt5 es:", price)
        tp=str(tp)
        tp=tp[:8]
        tp=float(tp)
        now = time.time()
        if comment == "5min":
           el_tiempo = int(now + 300)
        if comment == "15min":
           el_tiempo = int(now + 900)
        if comment == "30min":
           el_tiempo = int(now + 1800)
        if comment == "1hour":
           el_tiempo = int(now + 3600)

        buy_request = {
            "action": mt5.TRADE_ACTION_DEAL,
            "symbol": symbol,
            "volume": lot,
            "type": trade_type,
            "price": price,
            "sl": price + (price -tp),
            "tp": tp,
            "deviation": deviation,
            "magic": ea_magic_number,
            "comment": comment,
            "type_time": mt5.ORDER_TIME_SPECIFIED , # good till cancelled
            "expiration": el_tiempo,
            "type_filling": mt5.ORDER_FILLING_IOC,
        }
        # send a trading request
        result = mt5.order_send(buy_request)       
        print("¿orden enviada?")    
        print("resultado de la orden", result)  
    else:
        print("no puede vender")
        result = "no posible comprar"
        buy_request = "no posible comprar nene"
    return result, buy_request 

错误返回结果

OrderSendResult(retcode=10016, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Invalid stops', request_id=0, retcode_external=0, request=TradeRequest(action=1, magic=4494609, order=0, symbol='EURCHF', volume=0.1, price=0.97846, stoplimit=0.0, sl=0.978479, tp=0.978441, deviation=100, type=1, type_filling=1, type_time=2, expiration=1682463619, comment='1hour', position=0, position_by=0))

问题原因

  1. 止损计算逻辑错误+未满足平台最小止损距离要求
    卖单的止损(SL)应设置在当前报价上方,但你的计算方式sl = price + (price - tp)虽然数值方向正确,但计算出的SL与当前价格的差值(0.000019)远低于RoboMarkets对EURCHF要求的最小止损距离,平台直接判定止损无效。

  2. MT5初始化时机错误
    你在调用get_info(symbol)(推测内部调用了mt5.symbol_info_tick)之后才执行mt5.initialize(),未初始化就调用MT5 API会导致奇怪的错误返回(1, 'Success'),同时可能影响后续报价获取的准确性。

  3. 手动截断TP精度破坏价格格式
    通过字符串截断处理TP的方式(tp=str(tp); tp=tp[:8]; tp=float(tp))会强制修改价格精度,不符合EURCHF的报价精度要求(通常为5位小数),进一步导致止损止盈参数无效。


修复方案

1. 修正止损止盈计算逻辑,遵守平台规则

先获取品种的点值和最小止损距离,再计算符合要求的SL/TP:

# 在初始化后添加以下代码获取品种关键参数
symbol_info = mt5.symbol_info(symbol)
point = symbol_info.point
min_stop_distance = symbol_info.trade_stops_level * point  # 平台要求的最小止损距离

# 替换原卖单逻辑中的SL计算
elif action =='sell':
    trade_type = mt5.ORDER_TYPE_SELL
    price = mt5.symbol_info_tick(symbol).bid
    print(price)
    # 确保SL距离不小于最小要求,TP方向正确
    sl = price + min_stop_distance  # 严格遵循平台最小止损
    # 如果传入的TP符合要求则使用,否则按规则生成
    if tp < price and (price - tp) >= min_stop_distance:
        tp = round(tp, symbol_info.digits)
    else:
        tp = price - 50 * point  # 示例:默认50点止盈,可按需调整

2. 调整MT5初始化时机

将mt5.initialize()移至所有MT5 API调用之前,避免未初始化调用:

def open_trade_sell2(action, symbol, lot, tp, deviation, ea_magic_number,comment):
    '''下单函数'''
    # 优先初始化MT5
    if not mt5.initialize():
        print("initialize() failed, error code =",mt5.last_error())
        return None, None  # 用返回替代quit(),避免终止整个程序
    
    # 之后再执行其他API调用
    symbol_info = get_info(symbol)
    print("symbol info",symbol_info)
    
    lasttick=mt5.symbol_info_tick(symbol)
    print(lasttick)
    # 后续逻辑...

3. 移除手动截断TP的代码,用精度对齐替代

# 替换原TP截断代码
digits = symbol_info.digits
tp = round(tp, digits)  # 按品种精度对齐价格

4. 可选:调整订单有效期参数

若IOC订单配合指定有效期仍有问题,可尝试改用无限有效期:

buy_request = {
    # ... 其他参数
    "type_time": mt5.ORDER_TIME_GTC,  # 取消有效期限制
    # "expiration": el_tiempo,  # 注释或删除该行
    # ...
}

验证步骤

  • 调用print(symbol_info)查看trade_stops_level、digits、point参数,确认平台规则。
  • 下单前打印SL、TP、Price的值,检查:卖单SL > Price,TP < Price,且SL-Price >= 最小止损距离。

内容的提问来源于stack exchange,提问作者jjjjj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 11:32:34