问题描述
解决方案
为了实现“风险最低”的资产配置策略,最科学的方法是采用最小方差模型(Minimum Variance Model)。该模型利用现代投资组合理论(MPT),通过计算不同资产之间的历史波动率和相关性,自动计算出组合波动率最低的权重配置。
为了进一步降低风险,我们在资产池中选择了低相关性且本身波动较小的ETF标的,包括债券、货币基金、黄金和宽基指数。
策略核心逻辑
- 资产池选择:
- 国债ETF (511010.XSHG):核心防守资产,波动极低。
- 银华日利 (511880.XSHG):货币基金ETF,现金管理工具,风险接近零。
- 黄金ETF (518880.XSHG):避险资产,与其他资产相关性低。
- 沪深300ETF (510300.XSHG):少量配置以获取市场平均收益,利用负相关性对冲风险。
- 优化目标:使用聚宽内置的
MinVariance优化器,目标是最小化组合的历史方差(风险)。 - 调仓频率:按月调仓,根据最新的市场波动率调整权重。
以下是完整的策略代码:
# -*- coding: utf-8 -*-
# 导入函数库
from jqdata import *
from jqlib.optimizer import *
import pandas as pd
def initialize(context):
"""
初始化函数
"""
# 1. 设定基准(这里使用国债指数作为基准更合适,但为了对比通常设为沪深300)
set_benchmark('000300.XSHG')
# 2. 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 3. 过滤掉order系列API产生的比error级别低的log
log.set_level('order', 'error')
# 4. 设定ETF基金交易手续费
# ETF买卖无印花税,佣金设为万分之三,最低5元
set_order_cost(OrderCost(open_tax=0, close_tax=0, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='fund')
# 5. 定义低风险资产池
# 511010: 国债ETF (极低风险)
# 511880: 银华日利 (货币ETF,极低风险)
# 518880: 黄金ETF (避险资产,低相关性)
# 510300: 沪深300ETF (权益类资产,用于分散化)
g.etf_pool = [
'511010.XSHG',
'511880.XSHG',
'518880.XSHG',
'510300.XSHG'
]
# 6. 设定调仓周期:每月第一个交易日运行
run_monthly(rebalance, monthday=1, time='09:30')
def rebalance(context):
"""
调仓函数:计算最小方差权重并调仓
"""
log.info("开始进行最小方差资产配置优化...")
# 获取当前日期
date = context.previous_date
# 1. 使用聚宽内置优化器计算权重
# target=MinVariance(count=250): 目标是最小化过去250个交易日的组合方差
# constraints: 约束条件,这里限制总权重之和为1 (100%仓位)
# bounds: 边界条件,每个标的权重在 0.0 到 1.0 之间 (不做空)
try:
optimized_weight = portfolio_optimizer(
date=date,
securities=g.etf_pool,
target=MinVariance(count=250),
constraints=[WeightConstraint(low=1.0, high=1.0)],
bounds=[Bound(0.0, 1.0)],
default_port_weight_range=[0.0, 1.0],
ftol=1e-09,
return_none_if_fail=True
)
except Exception as e:
log.error("优化器运行异常: %s" % e)
return
# 2. 检查优化结果
if optimized_weight is None:
log.warn("组合优化失败,本次不调仓")
return
log.info("目标权重: \n%s" % optimized_weight)
# 3. 执行调仓
# 获取当前总资产
total_value = context.portfolio.total_value
# 先卖出不在目标池或权重降低的标的
current_positions = context.portfolio.positions
for security in current_positions:
if security not in optimized_weight.index:
order_target_value(security, 0)
# 根据优化后的权重买入/调整
for security in g.etf_pool:
if security in optimized_weight.index:
target_value = total_value * optimized_weight[security]
order_target_value(security, target_value)
def handle_data(context, data):
"""
按分钟回测时必须实现,这里为空
"""
pass
策略详解
-
资产选择逻辑:
- 策略没有只选择单一资产,而是构建了一个组合。因为单一资产(即使是债券)也面临特定风险(如利率风险)。
- 通过引入货币ETF和国债ETF,奠定了极低波动的基础。
- 优化器会自动识别出权益类资产(沪深300)的高波动性,因此在计算“最小方差”时,通常会给予权益类资产极低的权重(往往低于5%),而将绝大部分仓位分配给国债和货币基金。
-
优化器设置 (
MinVariance):- 使用了
jqlib.optimizer中的MinVariance目标函数。 count=250表示使用过去一年的历史数据来计算协方差矩阵。这意味着策略会根据长期的波动特征来配置资产,避免因短期市场噪音频繁剧烈调仓。
- 使用了
-
预期表现:
- 回撤极小:由于重仓债券和货币基金,历史最大回撤通常控制在极低水平(往往小于2%)。
- 收益稳定:收益率略高于货币基金,属于典型的理财替代型策略。
Q&A
Q: 为什么不直接全仓买货币基金?
A: 全仓货币基金虽然风险极低,但收益也最低且无法抵抗通胀。最小方差策略利用了资产间的不完全相关性(例如股票跌时债市可能涨),在数学上可以在保持同等低风险水平的同时,通过分散化获得比单一货币基金稍高的夏普比率。
Q: 这个策略适合什么资金?
A: 适合对回撤极其敏感、追求绝对收益、或者作为闲置资金管理的投资者。
Q: 如果我想稍微提高一点收益怎么办?
A: 可以修改代码中的 target 参数。将 MinVariance 改为 RiskParity(风险平价),这会稍微增加股票和黄金的配置比例,风险略微上升,但长期潜在收益会更高。