为何在无卖空约束的最小方差投资组合优化中得到负权重?
无卖空约束下最小方差投资组合求解问题
我需要使用CVXR库求解包含183只资产的最小方差投资组合权重,优化问题如下:
- 目标函数:$\min_{w} \frac{1}{2}w^T\sigma w$
- 约束条件:
- $\sum w = 1$
- $w \geq 0$
其中:
- $\sigma$是183×183的半正定方差-协方差矩阵,由313条资产历史收益率估计得到
- $w$为各资产的组合权重
我尝试了以下代码,但验证发现权重出现极小的负值,违反了无卖空约束:
library(readxl) library(matrixcalc) Library(CVXR) # 大小写错误 Return <- read_excel ("datasets.xlsx") Return <- as.data.frame(Return) sigma <- cov(Return) is.positive.definite(sigma) [1] TRUE #quadratic programming w <- Variable(183) objective <- Minimize((1/2) %*% (quad_form(w, sigma))) # 目标函数写法错误 constraints <- list( w >= 0, sum(w) == 1 ) problem <- Problem(objective, constraints) soln <- solve(problem) b <- soln$getValue(w) #verify sum(b) [1] 1 min(b) [1] -5.781906e-22
问题原因及修正方案
- R包加载的大小写错误:R语言对大小写敏感,
Library(CVXR)必须改为library(CVXR),否则无法正确加载CVXR库。 - 目标函数的语法错误:CVXR中
quad_form(w, sigma)已经返回合法的二次型表达式,不能用矩阵乘法运算符%*%来乘以1/2,需改用普通标量乘法*。错误写法会导致求解器解析异常,间接影响约束处理。 - 极小负值的数值精度问题:你得到的
-5.781906e-22是浮点运算的精度误差,本质上与0无差异。可以通过截断极小负值为0,或给求解器设置更高精度参数来处理。
修正后的代码
library(readxl) library(matrixcalc) library(CVXR) # 修正大小写 Return <- read_excel("datasets.xlsx") Return <- as.data.frame(Return) sigma <- cov(Return) is.positive.definite(sigma) # 二次规划求解 w <- Variable(183) # 修正目标函数写法 objective <- Minimize(0.5 * quad_form(w, sigma)) constraints <- list(w >= 0, sum(w) == 1) problem <- Problem(objective, constraints) # 设置更高求解精度,减少浮点误差 soln <- solve(problem, solver = "ECOS", control = list(abstol = 1e-10, reltol = 1e-10)) b <- soln$getValue(w) # 处理精度误差:将极小负值设为0 b[b < 0] <- 0 # 重新归一化确保权重和为1 b <- b / sum(b) # 验证 sum(b) min(b)
额外说明
- 对于半正定矩阵的二次规划问题,CVXR默认求解器可正常处理,提高精度参数能进一步减少浮点误差带来的极小负值。
- 截断极小负值并重新归一化是这类数值问题的常用处理方式,不会对组合方差产生显著影响。
内容的提问来源于stack exchange,提问作者Vito
相关产品推荐
相关产品推荐

