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

聚宽实盘卖出:如何使用 closeable_amount 控制可卖数量?

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

问题描述



Title: 聚宽实盘卖出:如何使用 closeable_amount 控制可卖数量?

Question: 如何在聚宽实盘策略中计算目标市值差额,并结合 closeable_amount 防止卖出不可用持仓?

解决方案

在聚宽(JoinQuant)平台进行实盘或模拟盘交易时,由于A股实行 T+1 交易制度,当天买入的股票当天无法卖出。如果策略在计算调仓时,简单地使用目标市值差额计算出需要卖出的股数,并直接下单,很容易因为卖出尚未可用的持仓而导致委托失败或系统报错。

为了解决这一问题,我们需要在计算出目标卖出股数后,结合 Position 对象的 closeable_amount(可卖出仓位)属性进行二次校验,确保卖出数量不超过实际可卖数量。


一、 核心概念解析

  1. closeable_amount(可卖出仓位)
    在聚宽 API 中,context.portfolio.positions[security].closeable_amount 表示当前持仓中可以卖出的股票数量(即排除了当天买入的、以及已被其他未完成订单冻结的股数)。

  2. 目标市值差额计算
    调仓时,我们通常会计算目标持仓市值与当前持仓市值的差额。若:
    $$\text{目标股数} < \text{当前总股数}$$
    则需要卖出差额部分:
    $$\text{计划卖出股数} = \text{当前总股数} - \text{目标股数}$$

  3. 安全卖出控制
    为了防止废单,实际下单的卖出股数应为:
    $$\text{实际卖出股数} = \min(\text{计划卖出股数}, \text{closeable_amount})$$


二、 核心代码实现方法

以下是在 handle_data 或定时运行函数中,安全计算并执行卖出调仓的逻辑:

def adjust_position_to_target(context, security, target_value):
    # 1. 获取当前标的的最新价格
    current_data = get_current_data()
    price = current_data[security].last_price
    if price <= 0:
        return
        
    # 2. 计算目标股数(按100股向下取整)
    target_amount = int(target_value / price / 100) * 100
    
    # 3. 获取当前持仓信息
    position = context.portfolio.positions[security]
    current_amount = position.total_amount
    closeable = position.closeable_amount
    
    # 4. 判断是否需要卖出
    if target_amount < current_amount:
        # 计划卖出股数
        sell_amount = current_amount - target_amount
        # 结合 closeable_amount 限制实际卖出股数,防止超卖报错
        actual_sell_amount = min(sell_amount, closeable)
        
        if actual_sell_amount > 0:
            # 卖出时 amount 传入负数
            order(security, -actual_sell_amount)
            log.info(f"计划卖出 {security} {sell_amount}股,实际可卖 {actual_sell_amount}股,已下单。")
    
    # 5. 判断是否需要买入
    elif target_amount > current_amount:
        buy_amount = target_amount - current_amount
        # 检查可用资金是否足够
        cash = context.portfolio.available_cash
        if cash >= buy_amount * price:
            order(security, buy_amount)
            log.info(f"买入 {security} {buy_amount}股。")

三、 完整策略示例(双均线调仓)

下面是一个完整的聚宽策略,展示了如何在每日调仓中,安全地使用 closeable_amount 控制卖出数量:

# 导入聚宽函数库
import jqdata

def initialize(context):
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    
    # 定义操作股票
    g.security = '000001.XSHE' # 平安银行
    
    # 每天 09:30 运行
    run_daily(market_open, time='09:30')

def market_open(context):
    security = g.security
    
    # 获取历史数据计算均线
    close_data = attribute_history(security, 10, '1d', ['close'])
    ma5 = close_data['close'][-5:].mean()
    ma10 = close_data['close'][-10:].mean()
    
    # 获取当前账户总资产
    total_value = context.portfolio.total_value
    
    # 设定目标仓位比例
    if ma5 > ma10:
        # 金叉:目标配置 80% 仓位
        target_ratio = 0.8
    else:
        # 死叉:目标配置 0% 仓位(清仓)
        target_ratio = 0.0
        
    # 计算目标市值
    target_value = total_value * target_ratio
    
    # 执行安全调仓
    safe_order_target_value(context, security, target_value)

def safe_order_target_value(context, security, target_value):
    current_data = get_current_data()
    price = current_data[security].last_price
    if price <= 0:
        return
        
    # 计算目标股数(100股整数倍)
    target_amount = int(target_value / price / 100) * 100
    
    position = context.portfolio.positions[security]
    current_amount = position.total_amount
    closeable = position.closeable_amount
    
    if target_amount < current_amount:
        # 需要减仓或清仓
        sell_amount = current_amount - target_amount
        # 核心安全控制:确保卖出量不超过可卖量
        actual_sell_amount = min(sell_amount, closeable)
        
        if actual_sell_amount > 0:
            order(security, -actual_sell_amount)
            log.info(f"调仓卖出:{security} 计划卖出 {sell_amount} 股,受 closeable_amount 限制,实际执行卖出 {actual_sell_amount} 股。")
            
    elif target_amount > current_amount:
        # 需要加仓
        buy_amount = target_amount - current_amount
        cash = context.portfolio.available_cash
        # 确保资金充足
        if cash < buy_amount * price:
            buy_amount = int(cash / price / 100) * 100
        if buy_amount > 0:
            order(security, buy_amount)
            log.info(f"调仓买入:{security} 执行买入 {buy_amount} 股。")

四、 避坑提示

  1. 不要跨日期缓存 closeable_amount:持仓状态每天都会随清算而更新,必须在每次下单前实时通过 context.portfolio.positions[security].closeable_amount 获取最新值。
  2. 未成交挂单的影响:如果策略在盘中已经提交了卖出限价单但尚未成交,这部分股数会被冻结,closeable_amount 会相应减少。因此,在调仓前建议先调用 get_open_orders() 检查并撤销未完成的订单,释放可卖额度。