这个例子展示了如何使用基于问题的方法来解决混合整数二次规划(MIQP)投资组合优化问题。迭代求解一系列局部近似于混合整数线性规划(MILP)问题。有关基于求解器的方法,请参见混合整数二次编程产品组合优化:求解器为基础。
正如Markowitz所示(“投资组合选择”,J. Finance第7卷,第1卷,第77-91号),1952年3月77-91),可以表达许多投资组合优化问题作为二次编程问题。假设你有一组N
资产并希望选择一个投资组合,与
作为资产的投资的一小部分
。如果你知道矢量
每个资产的平均回报,以及协方差矩阵
对于给定的风险厌恶程度,回报是多少
您最大限度地提高风险调整的预期返回:
这quadprog
求解器解决了这种二次编程问题。但是,除了普通的二次编程问题之外,您可能希望以各种方式限制投资组合,例如:
不超过m
投资组合的资产,在哪里m <= n
。
至少有m
投资组合的资产,在哪里0
拥有半连续约束,意思 , 或者 一些固定的分数 和 。
您不能包含这些约束quadprog
。困难是限制的离散性。此外,虽然混合整数线性编程求解器确实处理了离散的约束,但它没有地解决二次目标函数。
这个例子构造了一系列满足约束条件,并逐渐逼近二次目标函数的MILP问题。虽然此技术适用于此示例,但它可能不适用于不同的问题或约束类型。
首先建模约束。
是资产分配分数的矢量 对于每一个人 。要模拟投资组合中的资产数量,您需要指示器变量 这样 什么时候 , 和 什么时候 。要获得满足此限制的变量,请设置 向量是二进制变量,并施加线性约束
这些不平等都强制执行这一点 和 在完全同时为零,它们也强制执行 每当 。
此外,为了强制执行投资组合中资产数量的约束,施加线性约束
首先配制,您尝试最大化目标函数。但是,所有优化工具箱™索盘最小化。因此,为最小化目标的负面制定问题:
该目标函数是非线性的。MILP求解器需要线性目标函数。有一种标准技术来重构这个问题,以线性物镜物镜和非线性约束。介绍一个松弛变量 代表二次术语。
当您迭代地解决MILP近似时,您包括新的线性约束,每个线性约束近似于当前点附近的非线性约束。特别是 在哪里 是一个常数矢量和 是一个变矢量,约束条件的一阶泰勒近似是
更换 经过 给
对于每个中间解决方案 您介绍了一个新的线性约束 和 作为上面表达式的线性部分:
这具有表单 , 在哪里 ,有一个 乘法器为 术语和 。
这种向问题中添加新的线性约束的方法称为切面法。详情请参见J. E. Kelley, Jr.。求解凸规划的切割平面法j . Soc。工业上。达成。数学。第8卷,第4期,703-712页,1960年12月。
为了表达优化问题:
决定你的变量代表什么
在这些变量中表达下限和上限
提供线性平等和不等式表达
加载问题的数据。该数据在矢量中有225个预期返回R.
和225×225矩阵中的回报的协方差问:
。数据与在投资组合优化问题上使用二次规划的例子相同。
加载Port5.r = mean_return;q =相关性。*(stddev_return * stddev_return');
设置资产的数量N
。
n =长度(r);
创建连续变量XVARS.
代表资产分配分数,二进制变量vvars.
表示是否关联XVARS.
是零或严格阳性的,Zvar.
代表这一点
变量,一个正标量。
xvars = optimvar ('xvars',n,1,'indowbound',0,'上行',1);vvars = Optimvar('vvars',n,1,'类型'那'整数'那'indowbound',0,'上行',1);zvar = Optimvar('ZVAR',1,'indowbound',0);
所有的下界2n + 1
问题中的变量为零。的上限XVARS.
和yvars.
变量是一个,而且Zvar.
没有上限。
将解决方案中的资产数量设置为100到150之间。将这个约束以这种形式纳入问题中,即
通过编写两个线性约束:
m = 150;m = 100;qpprob = OptimProblem('ObjectiveSense'那'最大化');qpprob.constraints.mconstr = sum(vvars)<= m;qpprob.constraints.mconstr2 = sum(vvars)> = m;
包括半连续约束。采取最小的非零部分资产0.001
对于每个资产类型,最大分数0.05
。
fmin = 0.001;fmax = 0.05;
包括不平等 和 。
qpprobe . constraints .fmaxconstr = xvars <= fmax* vars;qpprobe . constraints .fminconstr = fmin* vars <= xvars;
包括投资组合100%投入的约束,意思 。
qpprob.constraints.Allin = Sum(xvars)== 1;
设置风险厌恶系数
至One hundred.
。
lambda = 100;
定义目标函数 并在问题中包含它。
qpprob.objective = r'* xvars - lambda * zvar;
为了迭代地解决问题,首先解决当前约束的问题,该问题尚未反映任何线性化。
选项= Optimoptions(@Intlinprog,'展示'那'离开');%抑制迭代显示[xlinint,fval,extflagint,输出] =求解(qpprob,“选项”,选项);
为迭代准备一个停止条件:在松弛变量时停止 在真正二次值的0.01%以内。
thediff = 1的军医;iter = 1;%迭代计数器assets = xlinint.xvars;Truequadratic =资产'* Q *资产;zslack = xlinint.zvar;
保留计算的真正二次和松弛变量的历史记录。设置更严格的公差而不是默认值,以帮助迭代会聚到正确的解决方案。
历史= [stryquadratic,zslack];选项= Optimoptions(选项,'lpoptimalandaltolerance',1e-10,'相对golcerance',1e-8,......'约束专利',1e-9,'integertolerance',1E-6);
计算二次和松弛值。如果它们不同,则添加另一个线性约束并再次解决。
每一个新的线性约束 来自线性近似值
找到新的解决方案后,在旧解决方案和新解决方案之间使用线性约束。万博 尤文图斯这种包括线性约束的启发式方式可以比简单地采用新的解决方案更快。要使用解决方案而不是中途启发式,评论下面的“中途”行,并取消了以下一个。
尽管ABS((ZSLACK - RUREQUADRATIC)/ TRUEQUADRATIC)> CHEDIFF%相对错误constr = 2 *资产'* q * xvars - zvar <=资产'* q *资产;newname = ['迭代',num2str(erter)];qpprob.constraints。(newname)= contr;%解决了新约束的问题[xlinint,fval,extflagint,输出] =求解(qpprob,“选项”,选项);资产=(资产+ Xlinint.xvars)/ 2;从之前到当前的%中途%资产= XLININT(XVARS);%使用前一行或这个truequadratic = xlinint.xvars'* q * xlinint.xvars;zslack = xlinint.zvar;历史= [历史;真正的,zslack];iter = iter + 1;结尾
绘制Slack变量的历史和目标函数的二次部分,以了解它们如何融合。
情节(历史)传说('二次'那'松弛')包含('迭代号') 标题(“二次逼近和线性逼近(松弛)”)
MILP解决方案的质量是什么?这输出
结构包含该信息。在解决方案的目标上检查内部计算的界限之间的绝对差距。
disp(output.absolutegap)
0.
绝对间隙为零,表明MILP解决方案是准确的。
绘制最佳分配。用xlinint.xvars.
, 不是资产
, 因为资产
使用中途更新时可能不满足约束。
Bar(xlinint.xvars)网格在Xlabel('资产索引') ylabel ('投资比例') 标题(“最优资产配置”)
您可以轻松地看到所有非零资产分配都在半连续界限之间 和 。
有多少非零资产?约束是在100到150个非零资产之间。
总和(xlinint.vvars)
ans = 100.
这种分配的预期回报是什么,以及风险调整的返回的价值?
fprintf('预期的回报是%g,风险调整的返回是%g。\ n'那......r'* xlinint.xvars,fval)
预期返回是0.000595107,风险调整的返回是-0.0360382。
通过使用专门用于FinancialToolbox®的产品组合优化专门设计的功能,可以进行更详细的分析。有关显示如何使用投资组合类直接处理半连续和基数约束的示例,请参阅具有半连续和基数约束的投资组合优化(金融工具箱)。