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

joinquant 组合优化器:如何使用 MaxDrawdownConstraint 限制最大回撤?

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

问题描述

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

Title: joinquant 组合优化器:如何使用 MaxDrawdownConstraint 限制最大回撤?

Question: 在 joinquant 组合优化器中,如何设置 MaxDrawdownConstraint 来控制组合的最大回撤?

解决方案

JoinQuant 组合优化器与最大回撤控制

在 JoinQuant(聚宽)量化交易平台中,portfolio_optimizer(投资组合优化器)提供了强大的约束机制,帮助开发者在满足指定收益或风险目标的同时,对资产组合的各种风险指标进行精细化控制。

要限制投资组合的最大回撤,可以使用限制函数库中的 MaxDrawdownConstraint


一、MaxDrawdownConstraint 参数详解

MaxDrawdownConstraint 用于限制组合在历史观测窗口内的最大回撤幅度。

语法说明

MaxDrawdownConstraint(limit, count=250)
  • limit (float): 最大回撤的上限阈值。注意:须设置为负数,例如 -0.20 表示限制最大回撤不超过 20%,-0.15 表示不超过 15%。
  • count (int, 可选): 向前回溯计算收益率与回撤的历史交易日天数,默认值为 250(约 1 个交易年)。

示例

# 限制过去 250 个交易日内组合最大回撤不超过 20%
constraint = MaxDrawdownConstraint(limit=-0.20, count=250)

二、完整策略代码示例

以下示例展示了如何在月度调仓策略中,使用 portfolio_optimizer 优化资产权重,并加入 MaxDrawdownConstraint 限制组合最大回撤不超过 15%。

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(trade, monthday=1, time='09:30', reference_security='000300.XSHG')

def trade(context):
    # 选定股票池(例如沪深300成分股的前20只)
    securities = get_index_stocks('000300.XSHG')[:20]
    
    # 定义优化目标:组合风险最小化(最小化方差)
    target = MinVariance(count=250)
    
    # 定义约束条件:加入 MaxDrawdownConstraint 限制最大回撤不超过 15%
    constraints = [
        WeightConstraint(low=0.8, high=1.0),            # 组合总持仓权重限制在 80%~100%
        MaxDrawdownConstraint(limit=-0.15, count=250)    # 限制最大回撤 <= 15%
    ]
    
    # 设置单只标的权重边界(0% ~ 15%)
    bounds = [Bound(low=0.0, high=0.15)]
    
    # 运行组合优化器
    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:
        log.info("优化权重成功:", optimized_weight)
        total_value = context.portfolio.total_value
        
        # 卖出不在优化结果中的股票
        for stock in context.portfolio.positions.keys():
            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:
        log.warn("组合优化失败,保持当前持仓不变")

三、注意事项与使用建议

  1. 极值符号问题limit 必须为负数(如 -0.2),若误传正数(如 0.2)可能导致约束失效或优化器求解报错。
  2. 过严约束处理:如果设置的最大回撤限制过于严格(如 -0.05),在波动剧烈的市场环境下优化器可能无法找到可行解,导致返回 None。建议配合 return_none_if_fail=True 并编写回退逻辑。
  3. 与其它约束搭配:通常可与 AnnualStdConstraint(收益波动率限制)或 RiskParity(风险平价)组合使用,构建多维度的风险控制体系。