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

Matlab中fmincon实现CVaR优化:波动率约束下权重无差异求助

排查CVaR优化中权重不变的问题

看起来你在CVaR优化的目标函数实现上踩了几个关键的坑,这大概率是导致权重始终不变的核心原因。我来一步步帮你拆解问题并给出修正方案:

一、目标函数的核心错误

你当前的目标函数存在三个致命问题,直接导致优化器无法感知权重变化对CVaR的影响:

Riskfun=@(w) min(quantile(w * Scen_Rets',1-beta)+((1/size(Scen_Rets,1))*(1/(1-beta)))*(max(-w * Scen_Rets'-quantile(w * Scen_Rets',1-beta),0)));
  1. 多余的min()包裹:CVaR本身是一个标量值,不是需要求最小值的表达式,这个min()会把原本的CVaR计算结果(应该是标量)错误地当成向量取最小值,完全偏离了CVaR的定义。
  2. 符号逻辑错误:max(-w * Scen_Rets'-quantile(...),0)的符号完全搞反了。我们要计算的是收益低于分位数的短缺部分,正确的表达式应该是max(quantile(...) - w*Scen_Rets', 0)——当组合收益w*Scen_Rets'低于分位数时,这个值为正,代表下行短缺。
  3. 缺少求和操作:max()返回的是一个1×10000的向量,你直接和分位数相加,没有对这些短缺值求和取平均,导致目标函数输出的不是CVaR,而是一个无意义的向量最小值,对权重变化极不敏感。

二、修正后的CVaR目标函数

先给你一个符合标准定义的CVaR计算实现,你可以直接替换原目标函数:

% 先定义beta(比如95%置信水平,beta=0.05)
beta = 0.05;

% 修正后的目标函数(用嵌套函数更清晰)
Riskfun = @(w) calculate_cvar(w, Scen_Rets, beta);

% 独立的CVaR计算函数
function cvar_val = calculate_cvar(w, Scen_Rets, beta)
    % 计算组合在所有场景下的收益:Scen_Rets是10000×8,w是8×1,得到1×10000的收益向量
    port_rets = w' * Scen_Rets;
    % 获取(1-beta)分位数(比如beta=0.05时,取5%分位数,代表最差的5%收益)
    q = quantile(port_rets, 1 - beta);
    % 筛选出低于分位数的收益样本
    below_q = port_rets < q;
    % 计算CVaR:最差(1-beta)部分收益的平均值(标准下行CVaR定义)
    if any(below_q)
        cvar_val = mean(port_rets(below_q));
    else
        % 极端情况:没有样本低于分位数,CVaR等于分位数
        cvar_val = q;
    end
end

如果喜欢更简洁的写法,也可以用单行匿名函数:

Riskfun = @(w) begin
    port_rets = w' * Scen_Rets;
    q = quantile(port_rets, 1 - beta);
    cvar_val = mean(port_rets(port_rets < q));
end;

三、下一步排查步骤

修正目标函数后,如果权重还是不变,你可以按以下顺序排查:

  • 验证目标函数敏感性:手动输入两个完全不同的权重(比如全0向量和单资产权重1的向量),计算Riskfun(w1)和Riskfun(w2),如果结果不同,说明目标函数已经正常工作;如果结果相同,检查Scen_Rets的维度是否正确(确保w'*Scen_Rets能正确生成组合收益)。
  • 检查波动率约束逻辑:你用了1000个自助法协方差矩阵,要明确约束的是「所有矩阵对应的波动率都小于目标值」还是「平均波动率小于目标值」:
    • 如果是前者,约束可能过于严格,导致只有唯一解(比如最小方差组合);
    • 如果是后者,确认协方差矩阵的平均计算是否正确(比如Sigma_avg = mean(Sigma_bootstrap, 3),假设Sigma_bootstrap是8×8×1000的数组)。
  • 查看fmincon迭代过程:把优化选项的Display设为'iter',观察迭代过程中目标函数值和权重的变化:
    options = optimoptions('fmincon','Display','iter','Algorithm','sqp');
    
    如果目标函数值始终不变,说明优化器认为当前点已经是最小值;如果目标函数变化但权重不变,检查约束是否把权重锁死了(比如上下限设置过于严格)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:03:23