You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CVaR投资组合优化:Rglpk_solve_LP与LSopt结果差异及修正

问题根源

你的Rglpk_solve_LP实现的是单纯下侧CVaR最小化模型(仅控制风险,未纳入收益目标),而LSopt的目标是最大化你自定义的上侧条件收益(取收益高于95%分位数的均值)。当资产有正预期收益时,LP模型会优先选择低波动资产(牺牲收益换低风险),导致你自定义的CVaR值更负;而LSopt会偏向高收益资产,该值更高。当收益全为0时,两者的目标无收益差异,结果自然一致。

以下是两种修改LP模型的方式,使其纳入组合平均收益的考量:


方式一:最小化CVaR,同时约束组合平均收益不低于目标值

这种方式在控制风险(CVaR)的前提下,保证组合收益不低于设定目标。

修改后的完整代码:

library(neighbours)
library(NMOF)
library(Rglpk)

# Return / vol
ret <- c(0.039, 0.036, 0.092, 0.139, 0.094)
vol <- c(0.125, 0.074, 0.101, 0.204, 0.167)

ns <- 1000
na <- length(ret)
R <- randomReturns(na, ns, mean=ret, sd = vol)

b <- 0.95

## 设定目标收益(这里取资产预期收益的均值,可自行调整)
target_ret <- mean(ret)

## 构建LP模型
f.obj <- c(alpha = 1, x = rep(0, na), u = 1/rep((1 - b)*ns, ns))

# 基础约束:权重和为1,CVaR定义约束
C <- cbind(1, R, diag(nrow(R)))
C <- rbind(c(alpha = 0, x = rep(1, na), u = rep(0, nrow(R))), C)
const.dir <- c("==", rep(">=", nrow(C) - 1))
const.rhs <- c(1, rep(0, nrow(C) - 1))

# 添加平均收益约束:组合平均收益 >= target_ret
C <- rbind(C, c(alpha=0, x=colMeans(R), u=rep(0, ns)))
const.dir <- c(const.dir, ">=")
const.rhs <- c(const.rhs, target_ret)

sol.lp <- Rglpk_solve_LP(f.obj,
                         C,
                         const.dir,
                         rhs = const.rhs,
                         control = list(verbose = TRUE, presolve = TRUE))  

lp.w <- sol.lp$solution[2:(1+na)]

## LSopt部分保持不变
CVaR <- function(w, R, b) {
  Rw <- R %*% w
  mean(Rw[Rw >= quantile(Rw, b)])
}

nb <- neighbourfun(0, 1, type = "numeric", stepsize = 0.05)

sol.ls <- LSopt(CVaR,
                list(x0 = rep(1/na, na),
                     neighbour = nb,
                     nI = 1000),
                R = R, b = b)

ls.w <- sol.ls$xbest

# 比较结果
CVaR(lp.w, R, b)
CVaR(ls.w, R, b)

方式二:同时权衡收益与CVaR(最大化收益-风险加权和)

这种方式将收益和CVaR整合到同一个目标函数中,通过调整风险厌恶系数lambda平衡两者权重:

  • lambda越大,模型越看重风险(CVaR);越小,越看重收益。

修改后的完整代码:

library(neighbours)
library(NMOF)
library(Rglpk)

# Return / vol
ret <- c(0.039, 0.036, 0.092, 0.139, 0.094)
vol <- c(0.125, 0.074, 0.101, 0.204, 0.167)

ns <- 1000
na <- length(ret)
R <- randomReturns(na, ns, mean=ret, sd = vol)

b <- 0.95
lambda <- 1  # 风险厌恶系数,可根据需求调整

## 优化目标:最大化(组合平均收益 - lambda*CVaR)
# 转化为线性规划的最小化目标:lambda*CVaR - 组合平均收益
mean_ret_coef <- colMeans(R)
f.obj <- c(alpha = lambda, 
           x = -mean_ret_coef, 
           u = lambda/rep((1 - b)*ns, ns))

# 基础约束:权重和为1,CVaR定义约束
C <- cbind(1, R, diag(nrow(R)))
C <- rbind(c(alpha = 0, x = rep(1, na), u = rep(0, nrow(R))), C)
const.dir <- c("==", rep(">=", nrow(C) - 1))
const.rhs <- c(1, rep(0, nrow(C) - 1))

sol.lp <- Rglpk_solve_LP(f.obj,
                         C,
                         const.dir,
                         rhs = const.rhs,
                         control = list(verbose = TRUE, presolve = TRUE))  

lp.w <- sol.lp$solution[2:(1+na)]

## LSopt部分保持不变
CVaR <- function(w, R, b) {
  Rw <- R %*% w
  mean(Rw[Rw >= quantile(Rw, b)])
}

nb <- neighbourfun(0, 1, type = "numeric", stepsize = 0.05)

sol.ls <- LSopt(CVaR,
                list(x0 = rep(1/na, na),
                     neighbour = nb,
                     nI = 1000),
                R = R, b = b)

ls.w <- sol.ls$xbest

# 比较结果
CVaR(lp.w, R, b)
CVaR(ls.w, R, b)

补充说明

如果你的目标是让LP模型直接优化你自定义的CVaR(即最大化收益高于95%分位数的均值),由于该目标涉及分位数筛选(非连续线性关系),无法直接用线性规划实现。此时可以考虑将LSopt的目标改为最小化下侧CVaR,或者使用整数规划(但计算成本会显著上升)。

内容的提问来源于stack exchange,提问作者RL_student

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 19:42:02