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

joinquant 平台如何使用 AnnualStdConstraint 限制组合波动率?(附 Python 源码)

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

问题描述

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

Title: joinquant 组合优化:如何使用 AnnualStdConstraint 限制波动率?

Question: 请问在 joinquant 的投资组合优化器中,如何限制策略组合的年化收益率标准差(波动率)?

解决方案

joinquant 平台如何使用 AnnualStdConstraint 限制组合波动率?

在 JoinQuant(聚宽)平台中,通过 portfolio_optimizer(投资组合优化器)可以根据目标函数和约束条件自动求解最优资产权重。如果您希望将组合的风险控制在特定范围内,可以使用 AnnualStdConstraint(组合年化收益率标准差限制) 来约束组合的年化波动率。


1. AnnualStdConstraint API 详解

AnnualStdConstraint 用于设定组合年化收益率标准差(即年化波动率)的上限。

语法

AnnualStdConstraint(limit, count=250)

参数说明

  • limit (float):组合年化收益率标准差(波动率)的上限,例如 0.15 表示年化波动率不超过 15%。
  • count (int, 可选):计算收益率和波动率所向前参考的历史交易日天数,默认为 250(约 1 个交易年)。

2. 核心示例代码

下面的示例展示了如何在月度调仓策略中使用 portfolio_optimizer,并加入 AnnualStdConstraint 限制组合年化波动率不超过 15%。

# 导入 JoinQuant 聚宽函数库及优化器模块
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)
    
    # 按月定时运行调仓
    run_monthly(market_open, monthday=1, time='09:30', reference_security='000300.XSHG')

def market_open(context):
    # 设定候选股票池(以沪深300部分成分股为例)
    securities = get_index_stocks('000300.XSHG')[:20]
    
    # 优化目标:组合收益最大化
    target = MaxProfit(count=250)
    
    # 约束条件:
    # 1. 组合总权重在 90% 到 100% 之间
    # 2. 限制组合年化波动率(标准差)不超过 15%
    constraints = [
        WeightConstraint(low=0.9, high=1.0),
        AnnualStdConstraint(limit=0.15, count=250)
    ]
    
    # 单标的权重边界:每只股票权重在 0% 到 10% 之间
    bounds = [Bound(low=0.0, high=0.1)]
    
    # 运行投资组合优化器
    optimized_weight = portfolio_optimizer(
        date=context.previous_date,
        securities=securities,
        target=target,
        constraints=constraints,
        bounds=bounds,
        ftol=1e-09,
        return_none_if_fail=True
    )
    
    # 处理优化结果并调仓
    if optimized_weight is not None:
        print("优化计算成功,目标权重如下:")
        print(optimized_weight)
        
        total_value = context.portfolio.total_value
        # 卖出不在优化结果中的持仓
        for stock in context.portfolio.positions:
            if stock not in optimized_weight or optimized_weight[stock] == 0:
                order_target_value(stock, 0)
                
        # 按优化分配的权重下单
        for stock, weight in optimized_weight.items():
            order_target_value(stock, total_value * weight)
    else:
        print("警告:组合优化求解失败,请检查约束条件是否过于苛刻。")

3. 注意事项与常见问题

  1. 约束不可可行(Infeasible Solution):如果设置的 AnnualStdConstraint(limit=...) 过于严格(例如小于股票池中所有资产的最低波动率组合),优化器可能无法求解并返回 None。建议设置合理的阈值(如 0.15 - 0.25)或将 return_none_if_fail 设置为 False
  2. 配合其他约束使用:通常建议配合 WeightConstraint(总权重限制)或 Bound(单标的持仓上限)共同使用,以防资金过于集中在少数低波动股票上。
  3. 历史参考天数(count:默认参考过去 250 个交易日。如果股票上市时间较短,计算协方差矩阵或波动率可能受影响。