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

为什么使用 order_target_value 会产生非100整数倍的持仓?平仓失败如何解决?

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

问题描述

order_target_value仓位问题

rebalance的时候,采用order_target_value后,有个股出现了8460股的持仓,还成交了,第二天平仓失败,请问如何解决该问题?

解决方案

在 JoinQuant 平台进行 Rebalance 调仓时,使用 order_target_value 出现非 100 整数倍的持仓(如 8460 股)且第二天平仓失败,通常与交易品种的特殊规则除权除息有关。以下是具体的原因分析及解决方案:

一、 为什么会出现 8460 股的持仓?

  1. 科创板股票的交易规则
    如果该股票是科创板股票(代码以 688 开头),根据交易所规则,科创板单笔申报数量为 200 股起,按 1 股递增。因此,order_target_value 在计算目标价值对应的股数时,完全可能计算并成交 8460 股。这是符合交易所规则的正常现象。
  2. 发生了除权除息(送转股)
    如果该股票是普通 A 股,买入时必须是 100 的整数倍。但如果在持仓期间发生了送股或转增股本(例如 10 送 4.1),原本 6000 股的持仓会自动变成 8460 股。在开启了真实价格模式(set_option('use_real_price', True))时,系统会根据复权因子自动调整你的持仓数量。

二、 为什么第二天平仓会失败?

  1. 科创板市价单未设置“保护价”
    这是最常见的原因。科创板股票在使用市价单(MarketOrder)进行买卖时,必须指定保护价,否则订单会被直接废单。如果你在平仓时使用了类似 order_target(security, 0) 且默认是市价单,但没有传入保护价,就会导致平仓失败。
  2. 零股卖出规则限制
    A 股规则规定,卖出时如果数量不足 100 股(零股),必须一次性全部卖出。如果你在平仓时试图只卖出部分零股(例如想卖出 8400 股,留下 60 股),订单会被拒绝。
  3. 常规原因:停牌或跌停
    股票在第二天处于停牌状态,或者开盘即一字跌停,导致市价单无法撮合成交。

三、 如何解决该问题?

方案 1:清仓时统一使用 order_target(security, 0)

无论持仓是多少股(包含零股),只要是想全部平仓,最安全的方式是直接将目标股数设为 0。系统会自动处理全部卖出的逻辑。

# 卖出所有股票, 使这只股票的最终持有量为0
order_target(security, 0)

方案 2:针对科创板股票,添加保护价或使用限价单

如果你的股票池中包含科创板股票,在下单时必须处理保护价,或者改用限价单(LimitOrderStyle)。

# 假设 current_price 是当前价格,设置跌停价或较低的价格作为卖出保护价
protect_price = current_price * 0.8 

# 使用带保护价的市价单清仓
order_target(security, 0, style=MarketOrderStyle(limit_price=protect_price))

# 或者使用限价单清仓
order_target(security, 0, style=LimitOrderStyle(current_price * 0.98))

方案 3:手动计算 100 的整数倍进行调仓(替代 order_target_value)

如果你不希望出现非 100 整数倍的持仓(即使是科创板),可以放弃直接使用 order_target_value,改为自己计算目标股数,并向下取整到 100 的倍数,然后使用 order_target 下单:

def my_order_target_value(security, target_value, data):
    # 获取当前价格
    current_price = data[security].close
    if current_price == 0:
        return
    
    # 计算目标股数
    target_amount = target_value / current_price
    
    # 向下取整到 100 的整数倍
    target_amount = int(target_amount / 100) * 100
    
    # 使用 order_target 下单
    order_target(security, target_amount)

总结排查步骤
先检查该股票是否为科创板(688开头),如果是,请务必在下单函数中加入 MarketOrderStyle(保护价);如果不是,请检查日志中是否有除权除息提示,并在平仓时严格使用 order_target(sec, 0)