🚀 AI 一键生成 joinquant 策略代码
立即体验
👉 AI 生成代码 👈

为什么 JoinQuant 回测中股票的停止单(Stop Order)没有执行?

joinquant | 发布时间: 2026/6/24
以下内容由 EasyQuant 生成。

问题描述

为何停止单不执行

回测发现股票的停止单没有执行。如,在开盘的时候下一个股票的停止单,希望在当天盘中价格超过某一特定价格(order_price)的时候,将该单转为市价单或者限价单买入;如果盘中价格没有达到order_price,就不执行。但是在回测中发现不能成交,为何?
代码如下:
order_value(stk_code,stk_val,style=StopLimitOrderStyle("stop_loss", order_price, order_price))
试过StopLimitOrderStyle和StopMarketOrderStyle都不行。

解决方案

在 JoinQuant(聚宽)平台中,停止单(Stop Order)未执行或无法成交通常由以下几个核心原因导致。针对您希望“在盘中价格超过某一特定价格时买入”的需求,请逐一排查以下几点:

1. 触发模式(Mode)与当前价格的关系

根据 JoinQuant API 文档,停止单分为 stop_loss(止损模式)和 take_profit(止盈模式)。

  • 买入/做多时的止损模式(stop_loss):触发价必须大于下单时的最新价。
  • 买入/做多时的止盈模式(take_profit):触发价必须小于下单时的最新价。

排查点:如果您在开盘时下单,且开盘价已经高于或等于您设定的 order_price,系统会认为触发价不满足“大于最新价”的条件,该停止单会立即触发。如果此时资金不足或发生其他校验失败,订单会直接作废。

2. 资金未提前锁定导致触发时委托失败

API 文档明确指出:“停止单不会提前锁定持仓和资金,触发时不满足委托条件(如资金不足或可交易数量不足)直接委托失败。”

排查点:您使用的是 order_value。如果在开盘下达停止单后,您的策略又下达了其他买入订单消耗了可用资金(available_cash),当盘中价格真正突破 order_price 触发该停止单时,账户中可能已经没有足够的资金,导致订单直接被拒(Rejected)。建议在日志中检查是否有 WARNINGERROR 提示资金不足。

3. 限价单(Limit Order)的撮合机制问题

您使用的代码是:
order_value(stk_code, stk_val, style=StopLimitOrderStyle("stop_loss", order_price, order_price))
这表示当价格向上突破 order_price 时,触发一个限价为 order_price 的买单

排查点:在真实的上涨行情中,当价格突破 order_price 时,市场最新价往往已经高于 order_price。此时触发的限价买单(买入价 = order_price)会因为出价低于市场现价而挂单等待,如果价格继续上涨不回头,这个限价单将永远无法成交,并在收盘后自动撤销。
解决办法:如果您希望突破后必定买入,建议使用 StopMarketOrderStyle("stop_loss", order_price),触发后会以市价单(Market Order)参与撮合。

4. 回测频率(Frequency)的限制

停止单的盘中触发依赖于细粒度的价格切片。
排查点:如果您使用的是按天回测(Daily),引擎每天只在指定时间点(如 09:30)运行一次,无法精确捕捉盘中的价格突破轨迹。要使盘中停止单准确触发,必须使用按分钟(Minute)或按 Tick 回测

💡 综合修改建议

如果您确认回测频率已经是分钟级,且资金充足,建议将代码修改为市价停止单,并增加日志打印以追踪订单状态:

# 确保在分钟级回测下运行
def handle_data(context, data):
    # 获取当前最新价
    current_price = data[stk_code].price
    
    # 确保触发价严格大于当前价,否则会立即触发
    if order_price > current_price:
        # 使用 StopMarketOrderStyle 确保突破后以市价成交,避免限价单挂单不成交
        order = order_value(
            stk_code, 
            stk_val, 
            style=StopMarketOrderStyle("stop_loss", order_price)
        )
        if order:
            log.info(f"成功下达停止单,触发价: {order_price}")
        else:
            log.error("停止单下达失败,请检查资金或标的状态")
    else:
        log.info(f"当前价 {current_price} 已超过目标价 {order_price},可直接下市价单买入")
        order_value(stk_code, stk_val)

总结检查清单

  1. 检查回测频率是否为分钟级
  2. 检查下单那一刻的 current_price 是否严格小于 order_price
  3. 检查触发瞬间账户是否有足够的 available_cash
  4. 改用 StopMarketOrderStyle 避免突破后限价单无法成交。