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

聚宽多仓位组合管理:如何合并同一标的权重避免重复下单?

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

问题描述



Title: 聚宽 多仓位组合管理:如何合并同一标的权重避免重复下单?

Question: 当一个 ETF 同时出现在多个策略仓位中时,如何在聚宽中合并目标权重并避免重复下单?

解决方案

聚宽多仓位组合管理:如何合并同一标的权重避免重复下单?

在构建多因子策略、多策略组合或分仓操作时,量化交易者经常会遇到一个经典问题:同一只标的(例如某只热门ETF)同时被多个子策略选中,并分配了不同的权重。

如果每个子策略独立运行并直接调用 orderorder_value 下单,会导致以下痛点:

  1. 重复下单:产生不必要的交易碎片,增加交易佣金与印花税成本。
  2. 仓位冲突:前一个策略刚买入,后一个策略执行平仓,导致持仓混乱。
  3. 资金占用不合理:无法精准控制整体组合的风险暴露。

本文将为您提供在聚宽(JoinQuant)平台中进行多仓位管理、合并同一标的权重并避免重复下单的完整解决方案。


一、 核心解决思路:全局权重合并与目标价值调仓

在聚宽中,避免重复下单的最佳实践是**“集中决策,统一调仓”**。具体步骤如下:

  1. 初始化多仓位:使用 set_subportfolios 划分不同的策略账户(如股票仓位、期货仓位等)。
  2. 收集并合并权重:在调仓时,不立即下单,而是先将所有子策略对同一标的(如 ETF)的期望权重(或目标价值)进行累加合并。
  3. 计算目标总价值:根据当前账户的总资产(context.portfolio.total_value)计算出该标的合并后的目标绝对价值。
  4. 使用目标价值下单 API:调用 order_target_value 一步到位调整到目标仓位。聚宽引擎会自动计算当前持仓与目标持仓的差额,仅对差额部分进行单笔下单,从而彻底避免重复下单。

二、 聚宽 Python 策略源码实现

以下是一个完整的聚宽策略示例。我们创建了两个虚拟的子策略,它们分别对一组 ETF 进行打分和权重分配。策略在每月初运行,自动合并相同 ETF 的权重并进行精准调仓。

# 导入聚宽函数库
import pandas as pd
from jqdata import *

def initialize(context):
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    
    # 设定交易费用:买入万三,卖出万三加千一印花税,最低5元
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    
    # 初始化子账户:将资金等分为两个子仓位(例如:策略A仓位和策略B仓位)
    init_cash = context.portfolio.starting_cash / 2
    set_subportfolios([
        SubPortfolioConfig(cash=init_cash, type='stock'), # 子账户 0
        SubPortfolioConfig(cash=init_cash, type='stock')  # 子账户 1
    ])
    
    # 定时运行:每月第一个交易日开盘运行调仓
    run_monthly(rebalance_portfolio, monthday=1, time='09:30')

def rebalance_portfolio(context):
    log.info("--------- 开始多仓位合并调仓 ---------")
    
    # 1. 模拟子策略 A 选中的 ETF 及其目标权重
    strategy_a_weights = {
        '510300.XSHG': 0.4,  # 沪深300 ETF
        '510500.XSHG': 0.3,  # 中证500 ETF
        '159915.XSHE': 0.3   # 创业板 ETF
    }
    
    # 2. 模拟子策略 B 选中的 ETF 及其目标权重
    strategy_b_weights = {
        '510300.XSHG': 0.5,  # 沪深300 ETF (与策略A重合)
        '510050.XSHG': 0.3,  # 上证50 ETF
        '159915.XSHE': 0.2   # 创业板 ETF (与策略A重合)
    }
    
    # 3. 合并全局权重
    # 我们需要将两个子账户的权重映射到总账户资产中。由于资金各占50%,全局权重 = (策略A权重 * 0.5) + (策略B权重 * 0.5)
    global_weights = {}
    
    for stock, weight in strategy_a_weights.items():
        global_weights[stock] = global_weights.get(stock, 0.0) + weight * 0.5
        
    for stock, weight in strategy_b_weights.items():
        global_weights[stock] = global_weights.get(stock, 0.0) + weight * 0.5
        
    log.info("合并后的全局目标权重: %s" % str(global_weights))
    
    # 4. 获取当前总资产
    total_value = context.portfolio.total_value
    
    # 5. 获取当前持仓中,不在目标全局权重列表中的标的,并将其清仓
    current_positions = list(context.portfolio.positions.keys())
    for stock in current_positions:
        if stock not in global_weights:
            log.info("标的 %s 不在目标组合中,执行清仓。" % stock)
            order_target(stock, 0)
            
    # 6. 按照合并后的目标价值进行精准调仓(避免重复下单)
    # 默认在 subportfolios[0](主仓位)中统一管理合并后的现货头寸
    for stock, weight in global_weights.items():
        target_value = total_value * weight
        log.info("标的 %s 合并后目标价值为: %.2f 元" % (stock, target_value))
        # 使用目标价值下单,聚宽会自动计算差额并单笔补单/减仓
        order_target_value(stock, target_value, pindex=0)
        
    log.info("--------- 调仓完成 ---------")

三、 关键 API 与机制解析

  1. order_target_value(security, value, pindex=0):
    这是避免重复下单的灵魂函数。假设你当前持有 510300.XSHG 价值 10 万元,合并权重后计算出的目标价值为 15 万元。调用此函数后,系统不会先卖出 10 万再买入 15 万,也不会直接买入 15 万,而是自动计算差额(15万 - 10万 = 5万),仅下一笔 5 万元的买单。这极大地节省了滑点和佣金。

  2. context.portfolio.total_value:
    获取当前账户的动态总权益(包含现金和所有子仓位的持仓市值)。以此为基准计算绝对价值,能确保组合整体杠杆率和权重分配的精确性。

  3. set_subportfolios:
    通过划分不同的子账户,您可以清晰地在后台监控不同策略的资金曲线,但在实际下单执行阶段,通过全局合并逻辑在主仓位(pindex=0)中统一调仓,完美兼顾了“策略独立统计”与“交易集中执行”的需求。