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

joinquant 组合优化器:如何使用 IndustryDeviationConstraint 限制行业偏离度?

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

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: joinquant 组合优化器:IndustryDeviationConstraint 行业偏离度控制

Question: 如何在投资组合优化中限制相对于沪深300指数的行业偏离度?

解决方案

在 JoinQuant 中使用 IndustryDeviationConstraint 控制行业偏离度

在量化投资组合构造过程中,为了避免组合在某一特定行业过度集中或产生过大的行业风险暴露,通常需要限制组合相对于基准指数(如沪深300指数)的行业偏离度。聚宽(JoinQuant)提供了强大的投资组合优化器 portfolio_optimizer 以及行业偏离度约束类 IndustryDeviationConstraint,方便开发者精确控制行业暴露。


一、核心 API 介绍

1. portfolio_optimizer 优化器函数

用于在指定的约束条件下求解最优股票权重组合:

from jqlib.optimizer import portfolio_optimizer, MinVariance, IndustryDeviationConstraint, Bound

optimized_weight = portfolio_optimizer(
    date=context.previous_date,
    securities=g.buy_list,
    target=MinVariance(count=250),
    constraints=[...],
    bounds=[Bound(0.0, 0.1)],
    default_port_weight_range=[0.0, 1.0],
    ftol=1e-09,
    return_none_if_fail=True
)

2. IndustryDeviationConstraint 行业偏离度限制

设定某一行业权重与基准指数权重的偏离度上限。

  • 语法IndustryDeviationConstraint(industry_code, benchmark, limit)
  • 参数说明
    • industry_code: 单一行业代码或行业代码列表(例如 'HY001')。
    • benchmark: 基准指数代码(例如 '000300.XSHG')。
    • limit: 允许的最大偏离度(如 0.05 代表权重偏离上下限不超过 5%)。

二、完整策略实现示例

以下策略展示了如何在月度调仓时,筛选上证50成分股与ETF,并利用组合优化器将行业权重相对于沪深300指数的偏离度控制在 5% 以内。

import pandas as pd
from jqdata import *
from jqlib.optimizer import *

def initialize(context):
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    
    # 设置股票交易手续费
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    
    # 定时运行:每月第一个交易日开盘前与开盘时执行
    run_monthly(before_market_open, monthday=1, time='09:00', reference_security='000300.XSHG')
    run_monthly(market_open, monthday=1, time='09:30', reference_security='000300.XSHG')

def before_market_open(context):
    # 选取股票池:上证50部分成分股与指定ETF
    etf = ['159902.XSHE', '510050.XSHG']
    g.buy_list = list(get_index_stocks('000016.XSHG')[-15:]) + etf

def market_open(context):
    # 卖出不在股票池中的持仓
    sell_list = set(context.portfolio.positions.keys()) - set(g.buy_list)
    for stock in sell_list:
        order_target_value(stock, 0)
        
    # 使用组合优化器计算最优权重
    # 优化目标:组合风险最小化(最小化组合方差)
    # 约束条件:行业 HY001 相对沪深300偏离度不超过 5%
    optimized_weight = portfolio_optimizer(
        date=context.previous_date,
        securities=g.buy_list,
        target=MinVariance(count=250),
        constraints=[
            WeightConstraint(low=0.9, high=1.0),
            IndustryDeviationConstraint(industry_code='HY001', benchmark='000300.XSHG', limit=0.05)
        ],
        bounds=[Bound(0.0, 0.15)],
        default_port_weight_range=[0.0, 1.0],
        ftol=1e-09,
        return_none_if_fail=True
    )
    
    if optimized_weight is None:
        log.warn('组合优化失败,保持当前持仓或采用替代方案')
        return
        
    # 执行调仓
    total_value = context.portfolio.total_value
    for stock, weight in optimized_weight.items():
        target_val = total_value * weight
        order_target_value(stock, target_val)

三、注意事项

  1. 行业分类匹配:在使用 IndustryDeviationConstraint 时,请确保输入的 industry_code 与系统内定义的聚宽或申万行业代码一致。
  2. 求解失败处理:如果设置的约束条件过于苛刻(例如偏离度阈值过小或与单标的权重上限冲突),优化器可能求解失败并返回 None。建议设置 return_none_if_fail=True 并编写降级调仓逻辑。
  3. 历史数据窗口:优化器内部计算方差或收益率时,需要向前获取数据(例如 count=250),请确保策略开始运行前标的拥有足够的交易历史。