🚀 AI 一键生成 joinquant 策略代码

揭秘 JoinQuant 回测引擎:订单是如何成交的?(撮合机制详解)

joinquant | 发布时间: 2025/12/2
以下内容由 EasyQuant 生成。

问题描述

为什么我下单后没有成交,或者只成交了一部分?

解决方案

在聚宽(JoinQuant)平台进行回测或模拟交易时,下单后未成交或仅部分成交通常是由撮合机制、市场流动性限制、资金持仓限制交易规则导致的。

以下是导致该情况的详细原因分析及排查方法:

1. 撮合机制与价格原因

  • 限价单(Limit Order)未达到成交价
    • 原因:如果您下的是限价单,只有当市场价格满足条件时才会成交。
      • 买入:市场价 $\le$ 您的委托价。
      • 卖出:市场价 $\ge$ 您的委托价。
    • 现象:订单状态一直为 open(已委托),直到收盘后被系统自动撤销。
  • 涨跌停限制
    • 买入时:如果标的涨停,市价单会被直接撤销;限价单会挂单排队,但通常因为没有卖盘而无法成交。
    • 卖出时:如果标的跌停,市价单会被直接撤销;限价单会挂单排队,但通常因为没有买盘而无法成交。
  • 滑点(Slippage)影响
    • 原因:系统默认或用户设置了滑点(set_slippage)。
    • 逻辑:如果 最新价 + 滑点 超过了涨停价(买入时)或低于跌停价(卖出时),订单可能无法成交或被撤销。

2. 成交量与流动性限制(最常见原因)

聚宽为了模拟真实的交易环境,防止策略对市场产生过大冲击,对成交量有严格限制。

  • 成交量比例限制 (order_volume_ratio)
    • 机制:回测中默认开启了成交量限制。默认情况下,您的策略在某一根K线(Bar)上的成交量,不能超过该标的在真实市场中该K线总成交量的 25%(默认值)。
    • 现象:如果您下单数量很大,而该股票当天/当分钟交易不活跃,系统会强制只成交一部分,或者完全不成交。
    • 调整方法:可以在 initialize 中通过 set_option('order_volume_ratio', value) 修改比例(例如设为 1.0 表示允许成交该分钟全部真实成交量,但这会降低回测真实性)。
  • 盘口撮合限制(模拟交易)
    • 机制:如果在模拟交易中开启了盘口撮合(set_option('match_with_order_book', True)),系统会严格按照买一/卖一等盘口数据撮合。如果对手盘挂单量不足,您的订单将只能部分成交。

3. 账户资金与持仓限制

  • 资金不足
    • 原因:账户 available_cash 不足。
    • 注意:买入时不仅需要支付股价,还需要支付手续费(佣金、印花税等)。如果资金刚好只够买股票但不够付手续费,订单会被拒绝或调整数量。
  • 持仓不足(卖出时)
    • 原因:尝试卖出的数量超过了 closeable_amount(可卖持仓)。
  • T+1 规则
    • 原因:A股实行 T+1 制度。当天买入的股票,当天不能卖出。
    • 现象:虽然 total_amount(总持仓)显示有货,但 closeable_amount(可卖持仓)为 0,导致卖单无法生成或无效。

4. 数据与系统机制

  • 停牌
    • 如果股票在回测期间停牌,无法进行买卖操作。
  • 未上市或已退市
    • 在标的未上市或退市后的日期下单,订单无效。
  • 收盘自动撤单
    • 机制:所有未完成的订单(open 状态)将在本交易日结束后(通常是 15:00 后)自动撤销。如果当天没成交,第二天不会自动补单,需要策略重新下单。
  • Bar 数据撮合逻辑
    • 分钟/日频回测:限价单是在当前 Bar 结束时撮合的。如果这一分钟内价格波动虽然触及了限价,但 Bar 的收盘/最高/最低价逻辑判定未满足(取决于具体的撮合设置),也可能导致不成交。

5. 如何排查?

建议在代码中添加以下检查逻辑:

  1. 检查未完成订单:使用 get_open_orders() 查看订单状态。
  2. 检查日志:聚宽系统会在日志中打印警告信息(Warning),例如“资金不足”、“成交量超过限制”等。
  3. 打印账户信息:在下单前打印 context.portfolio.available_cashcontext.portfolio.positions[security].closeable_amount

Q&A

Q: 为什么我的市价单(Market Order)在涨停板买入失败?
A: 在回测和模拟中,如果标的涨停,市价买单会被直接撤销,因为在真实市场中涨停板通常无法以市价买入。

Q: 如何解决“成交量限制”导致的部分成交?
A: 您可以在 initialize 函数中设置 set_option('order_volume_ratio', 1.0) 来允许策略成交该时间段内市场真实成交量的 100%,但这可能会导致回测结果失真(高估了策略的资金容量)。

Q: 为什么我明明有持仓,却提示可卖数量为0?
A: 请检查是否受 T+1 规则限制。如果是当日买入的股票,当日不可卖出,closeable_amount 会为 0,直到下一个交易日才会变成可卖持仓。

Q: 为什么收盘后我的挂单不见了?
A: 聚宽遵循交易所规则,所有当日未成交的委托单会在收盘后(日终清算时)自动撤销。如果需要继续交易,需要在下一个交易日重新下单。