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

joinquant 平台如何使用风险平价模型(Risk Parity)进行资产配置?(附 Python 源码)

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

问题描述

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

Title: joinquant 组合优化器:如何使用风险平价模型配置资产?

Question: 请问在聚宽上怎么用 portfolio_optimizer 实现风险平价(Risk Parity)资产配置?

解决方案

什么是风险平价(Risk Parity)模型?

风险平价(Risk Parity)是一种经典的资产配置方法。与传统的等权重配置(Equal Weight)或均值-方差优化(Min Variance)不同,风险平价的核心思想是让组合中各类资产对组合总风险的贡献度相等(或符合预设的风险预算比例)。这种方法能够有效避免组合风险过度集中于高波动资产(如股票),在市场下行或高波动时期具有极佳的稳健性。

在聚宽(JoinQuant)平台上,我们无需自己编写复杂的二次规划求解器,可以直接调用内置的 portfolio_optimizer 函数,配合 RiskParity 目标函数来快速实现这一模型。


聚宽 API:portfolio_optimizerRiskParity 核心用法

在聚宽中,进行风险平价优化的核心调用格式如下:

from jqlib.optimizer import *

optimized_weight = portfolio_optimizer(
    date=context.previous_date,
    securities=g.buy_list,
    target=RiskParity(count=250, risk_budget=None),  # risk_budget为None时,默认每只标的对组合的风险贡献相等
    constraints=[MarketConstraint('stock', low=0.0, high=0.9)],  # 约束条件
    bounds=[Bound(0.0, 0.1)],  # 单只标的权重边界
    default_port_weight_range=[0.0, 1.0],
    ftol=1e-09,
    return_none_if_fail=True
)

核心参数解析:

  1. target = RiskParity(count=250, risk_budget=None)
    • count: 计算资产协方差矩阵和历史收益率时,向前获取的历史天数(默认250天)。
    • risk_budget: 风险预算。传入一个 pandas.Series,指定每只标的的风险贡献比例。如果设为 None,则代表等风险贡献(ERC, Equal Risk Contribution),即标准的风险平价。
  2. constraints:限制函数列表。例如可以使用 MarketConstraint 限制股票或基金的总权重,或使用 WeightConstraint 限制总仓位。
  3. bounds:单只标的的权重上下限。例如 Bound(0.0, 0.1) 表示每只资产的配置权重不能超过 10%。

完整策略源码示例

以下是一个实用的多资产(股票 + ETF)风险平价配置策略。策略每月初进行一次调仓,使用过去250个交易日的数据计算风险平价权重,并对股票和 ETF 的总权重分别进行限制。

# 导入聚宽函数库及优化器模块
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):
    log.info('今日调仓日期:%s' % context.current_dt.date())
    
    # 选定配置的资产池:5只代表性ETF(黄金、创业板、纳指、红利、医药)
    g.buy_list = [
        '159934.XSHE',  # 黄金ETF
        '159915.XSHE',  # 创业板ETF
        '513100.XSHG',  # 纳指ETF
        '510880.XSHG',  # 红利ETF
        '510050.XSHG'   # 上证50ETF
    ]

def market_open(context):
    # 1. 卖出不在资产池中的持仓
    sell_list = set(context.portfolio.positions.keys()) - set(g.buy_list)
    for stock in sell_list:
        order_target_value(stock, 0)
        
    # 2. 调用聚宽组合优化器计算风险平价权重
    # 约束条件:组合总权重在 90% 到 100% 之间;单只标的权重不超过 40%
    optimized_weight = portfolio_optimizer(
        date=context.previous_date,
        securities=g.buy_list,
        target=RiskParity(count=250, risk_budget=None),  # ERC等风险贡献
        constraints=[WeightConstraint(low=0.9, high=1.0)],
        bounds=[Bound(0.0, 0.4)],
        default_port_weight_range=[0.0, 1.0],
        ftol=1e-09,
        return_none_if_fail=True
    )
    
    # 3. 执行调仓
    if optimized_weight is None:
        log.warn('警告:组合优化失败,保持原仓位')
    else:
        log.info('优化后的资产权重:\n%s' % optimized_weight)
        total_value = context.portfolio.total_value  # 获取当前总资产
        for stock in optimized_weight.keys():
            target_value = total_value * optimized_weight[stock]  # 计算目标配置金额
            order_target_value(stock, target_value)  # 调整至目标权重

避坑指南与注意事项

  1. 数据依赖与停牌处理portfolio_optimizer 内部会获取历史收益率。如果资产池中有新上市标的(历史数据不足250天)或长期停牌标的,可能会导致协方差矩阵无法计算而优化失败。建议在 before_market_open 中剔除上市未满一年的新股。
  2. 开启真实价格模式:进行资产组合优化回测时,强烈建议在 initialize 中设置 set_option('use_real_price', True)。使用真实价格能确保分红送股后,账户资金和持股数量得到正确调整,避免未来函数干扰回测结果。