3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在量化交易中,**CPPI(Constant Proportion Portfolio Insurance,固定比例组合保险)**是一种经典的动态资产配置策略。其核心思想是:设定一个资产底线(Floor),将高于底线的安全垫(Cushion)乘以一个放大倍数(Multiplier)作为主动性风险资产的投资额度。
为了防止极端行情下的回撤失控,我们可以结合**滚动最高净值(Rolling Peak Value)**来实时监控组合回撤。当回撤触及设定的阈值时,通过动态调整放大倍数或直接限制最大仓位,实现平滑减仓,达到动态风控的目的。
g.max_net_value):每日收盘后或盘中实时更新自策略启动以来的账户最高总资产(context.portfolio.total_value)。current_drawdown):以下是在聚宽(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)
risk_factor(风控系数),避免了传统 CPPI 在触及保本线时瞬间平仓带来的高额滑点损失,实现了阶梯式减仓。context.portfolio.total_value 获取当前真实资产,切勿跨日期缓存或使用未来的复权因子,建议在 initialize 中开启 set_option('use_real_price', True) 以确保回测的真实性。