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

聚宽平台如何实现 CPPI 动态风控策略?(附滚动回撤与仓位调整 Python 源码)

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

问题描述

聚宽 CPPI 动态风控:如何根据组合回撤自动调整目标仓位?
在聚宽策略中,如何使用滚动最高净值计算组合回撤,并通过 CPPI 公式在回撤达到不同阈值时自动降低目标仓位?

解决方案

聚宽 CPPI 动态风控:根据组合回撤自动调整目标仓位

在量化交易中,**CPPI(Constant Proportion Portfolio Insurance,固定比例组合保险)**是一种经典的动态资产配置策略。其核心思想是:设定一个资产底线(Floor),将高于底线的安全垫(Cushion)乘以一个放大倍数(Multiplier)作为主动性风险资产的投资额度。

为了防止极端行情下的回撤失控,我们可以结合**滚动最高净值(Rolling Peak Value)**来实时监控组合回撤。当回撤触及设定的阈值时,通过动态调整放大倍数或直接限制最大仓位,实现平滑减仓,达到动态风控的目的。


一、 核心逻辑设计

  1. 滚动最高净值(g.max_net_value:每日收盘后或盘中实时更新自策略启动以来的账户最高总资产(context.portfolio.total_value)。
  2. 当前回撤(current_drawdown
    $$\text{当前回撤} = \frac{\text{滚动最高净值} - \text{当前总资产}}{\text{滚动最高净值}}$$
  3. CPPI 动态仓位调整
    • 正常状态(回撤 < 5%):仓位系数为 1.0(满额运行 CPPI 乘数)。
    • 一级预警(5% $\le$ 回撤 < 10%):仓位系数降至 0.5(风险资产仓位减半)。
    • 二级预警(回撤 $\ge$ 10%):仓位系数降至 0.1(接近空仓,仅保留极低仓位或强制平仓)。

二、 聚宽策略源码实现

以下是在聚宽(JoinQuant)平台运行的完整策略代码。策略以沪深300成分股为选股池,并结合 CPPI 动态回撤风控:

import jqdata
import numpy as np

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')
    
    # 全局变量初始化
    g.security = '000300.XSHG' # 示例交易标的(沪深300ETF)
    g.max_net_value = context.portfolio.total_value # 滚动最高净值
    
    # CPPI 参数
    g.floor_ratio = 0.85  # 保险底线比例(例如保证 85% 的本金安全)
    g.multiplier = 3.0    # 初始风险放大倍数
    
    # 运行函数:每天开盘和收盘运行
    run_daily(market_open, time='09:30')
    run_daily(after_market_close, time='15:30')

def market_open(context):
    # 1. 更新滚动最高净值
    current_value = context.portfolio.total_value
    if current_value > g.max_net_value:
        g.max_net_value = current_value
        
    # 2. 计算当前回撤
    current_drawdown = (g.max_net_value - current_value) / g.max_net_value
    
    # 3. 根据回撤幅度确定仓位风控系数 (Risk Control Factor)
    if current_drawdown < 0.05:
        risk_factor = 1.0
        status = "正常运行"
    elif 0.05 <= current_drawdown < 0.10:
        risk_factor = 0.5
        status = "一级预警(减仓50%)"
    else:
        risk_factor = 0.1
        status = "二级预警(减仓90%)"
        
    log.info("当前总资产: %.2f, 历史最高净值: %.2f, 当前回撤: %.2f%%, 风控状态: %s" % 
             (current_value, g.max_net_value, current_drawdown * 100, status))
             
    # 4. CPPI 动态计算目标仓位
    # 动态保险底线(Floor)= 历史最高净值 * floor_ratio
    dynamic_floor = g.max_net_value * g.floor_ratio
    
    # 安全垫(Cushion)
    cushion = max(0, current_value - dynamic_floor)
    
    # 目标风险资产暴露额度 = Cushion * Multiplier * 风控系数
    target_risk_value = cushion * g.multiplier * risk_factor
    
    # 限制最大投资额不超过当前总资产
    target_risk_value = min(target_risk_value, current_value)
    
    # 5. 执行调仓
    execute_trade(context, g.security, target_risk_value)
    
    # 记录数据画图
    record(drawdown=current_drawdown * 100, risk_factor=risk_factor)

def execute_trade(context, security, target_value):
    """根据目标价值调整仓位"""
    current_position_value = context.portfolio.positions[security].value
    
    # 如果目标价值与当前持仓价值偏差大于 1%,则进行调仓
    if abs(target_value - current_position_value) / context.portfolio.total_value > 0.01:
        log.info("调整 %s 仓位至目标价值: %.2f" % (security, target_value))
        order_target_value(security, target_value)

def after_market_close(context):
    # 收盘后再次更新最高净值,为明天开盘做准备
    current_value = context.portfolio.total_value
    if current_value > g.max_net_value:
        g.max_net_value = current_value
    log.info("今日收盘,滚动最高净值更新为: %.2f" % g.max_net_value)

三、 策略优势与注意事项

  1. 动态锁利:由于底线(Floor)是基于滚动最高净值计算的,当组合资产上涨时,底线也会随之抬高。这使得策略在牛市中能够锁住利润,在熊市中迅速切断亏损。
  2. 平滑过渡:通过引入 risk_factor(风控系数),避免了传统 CPPI 在触及保本线时瞬间平仓带来的高额滑点损失,实现了阶梯式减仓。
  3. 注意未来函数:在回测中,务必使用 context.portfolio.total_value 获取当前真实资产,切勿跨日期缓存或使用未来的复权因子,建议在 initialize 中开启 set_option('use_real_price', True) 以确保回测的真实性。