主要内容

通过使用黑色垃圾方法生成代码来优化投资组合

这个例子展示了如何从MATLAB®代码中生成一个MEX函数和C源代码,使用Black Litterman方法执行投资组合优化。

先决条件

这个示例没有先决条件。

关于hlblacklitterman函数

hlblacklitterman.m函数读取有关投资组合的财务信息,并使用Black Litterman方法执行投资组合优化。

类型hlblacklitterman
函数(呃,ps, w, pw,λ,θ)= hlblacklitterman(σδ,weq,τ,P, Q,ω)% # codegen % hlblacklitterman %这个函数执行之前%和视图的Black-Litterman混合到一个新的后估计回报他和Litterman %本文中描述的。%输入%δ-平衡投资组合的风险容忍度% weq重量平衡投资组合的资产%σ-先验协方差矩阵%τCoefficiet之前估计的不确定性的意思(pi) % P -选为视图矩阵(s) % Q -向量的回报%ω-方差矩阵的观点(对角线)%输出% Er -平均收益的后验估计% w -给定收益的均值和协方差的后验估计%计算的无约束权重。% lambda -衡量每个观点对后验估计的影响。% theta -在后验精度中先验和样本信息的比例的度量。这是第6页的公式(12)。PI = weq * sigma * delta;我们在很多地方使用,所以只计算一次ts =;这是第4页公式(8)的简化版本。呃=π' + ts * P ' *发票(P * t * P ' +ω)* (Q - P *π”); % We can also do it the long way to illustrate that d1 + d2 = I d = inv(inv(ts) + P' * inv(Omega) * P); d1 = d * inv(ts); d2 = d * P' * inv(Omega) * P; er2 = d1 * pi' + d2 * pinv(P) * Q; % Compute posterior estimate of the uncertainty in the mean % This is a simplified and combined version of formulas (9) and (15) ps = ts - ts * P' * inv(P * ts * P' + Omega) * P * ts; posteriorSigma = sigma + ps; % Compute the share of the posterior precision from prior and views, % then for each individual view so we can compare it with lambda theta=zeros(1,2+size(P,1)); theta(1,1) = (trace(inv(ts) * ps) / size(ts,1)); theta(1,2) = (trace(P'*inv(Omega)*P* ps) / size(ts,1)); for i=1:size(P,1) theta(1,2+i) = (trace(P(i,:)'*inv(Omega(i,i))*P(i,:)* ps) / size(ts,1)); end % Compute posterior weights based solely on changed covariance w = (er' * inv(delta * posteriorSigma))'; % Compute posterior weights based on uncertainty in mean and covariance pw = (pi * inv(delta * posteriorSigma))'; % Compute lambda value % We solve for lambda from formula (17) page 7, rather than formula (18) % just because it is less to type, and we've already computed w*. lambda = pinv(P)' * (w'*(1+tau) - weq)'; end % Black-Litterman example code for MatLab (hlblacklitterman.m) % Copyright (c) Jay Walters, blacklitterman.org, 2008. % % Redistribution and use in source and binary forms, % with or without modification, are permitted provided % that the following conditions are met: % % Redistributions of source code must retain the above % copyright notice, this list of conditions and the following % disclaimer. % % Redistributions in binary form must reproduce the above % copyright notice, this list of conditions and the following % disclaimer in the documentation and/or other materials % provided with the distribution. % % Neither the name of blacklitterman.org nor the names of its % contributors may be used to endorse or promote products % derived from this software without specific prior written % permission. % % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND % CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, % INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF % MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE % DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR % CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, % SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, % BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR % SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, % WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING % NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE % OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH % DAMAGE. % % This program uses the examples from the paper "The Intuition % Behind Black-Litterman Model Portfolios", by He and Litterman, % 1999. You can find a copy of this paper at the following url. % http:%papers.ssrn.com/sol3/papers.cfm?abstract_id=334304 % % For more details on the Black-Litterman model you can also view % "The BlackLitterman Model: A Detailed Exploration", by this author % at the following url. % http:%www.blacklitterman.org/Black-Litterman.pdf %

%#codegen.指令表示MATLAB代码是用于代码生成的。

生成用于测试的MEX函数

方法生成一个MEX函数codegen命令。

codegenhlblacklitterman-  args.{0,零(1,7),零(7,7),0,零(1,7),0,0}
代码生成成功。

在生成C代码之前,首先要在MATLAB中测试MEX函数,以确保它在功能上等同于原始MATLAB代码,并且不会发生运行时错误。默认情况下,codegen生成一个名为mex函数hlblacklitterman_mex在当前文件夹中。这允许您测试MATLAB代码和MEX函数,并比较结果。

运行MEX命令

调用生成的MEX函数

testmex();
视图1国家Pμw *澳大利亚0 0 7.576 2.095 4.328 - 1.524加拿大法国100 11.04 35.41 -29.5 9.288 -3.948德国日本美国英国0 4.506 11.05 -70.5 6.953 -9.462 8.069 - 58.57 0问5ω/τ0.0213λ0.317θ0.0714公关θ0.929视图1国家P w *澳大利亚0μ加拿大法国0 7.576 2.095 -29.5 9.288 -3.948 4.328 - 1.524 100年德国11.04 35.41 Japan 0 4.506 11.05 UK -70.5 6.953 -9.462 USA 0 8.069 58.57 q 5 omega/tau 0.0213 lambda 0.317 theta 0.0714 pr theta 0.929执行时间- MATLAB函数:0.017014秒执行时间- MEX函数:0.018006秒

生成C代码

cfg = coder.config (“自由”);codegen-Config.cfghlblacklitterman-  args.{0,零(1,7),零(7,7),0,零(1,7),0,0}
代码生成成功。

使用codegen与指定的配置cfg选项生成一个独立的C库。

检查生成的代码

默认情况下,为库生成的代码在文件夹中Codegen / lib / hbblacklitterman /

的文件是:

dirCodegen / lib / hlblacklitterman /
.hlblacklitterman_terminate.h . .hlblacklitterman_terminate。o. gitignore hlblacklitterman_types.h _clang-format interface垫inv.c codeInfo。垫inv.h codedescriptor。dmr inv.o compileInfo。pinv.c定义。txt pinv.h的例子。o hlblacklitterman。a rtgetinfo .c hlblacklitterman.c rtgetinfo .h hlblacklitterman.h rtGetInf.ho hlblacklitterman。o rtGetNaN.c hlblacklitterman_data.c rtGetNaN.h hlblacklitterman_data.h rtGetNaN.co hlblacklitterman_data。rt_nonfinite.c hlblacklitterman_initialize.c rt_nonfinite.h hlblacklitterman_initialize.h rt_nonfinite.co hlblacklitterman_initialize。o rtw_proj。tmw hlblacklitterman_rtw。mk rtwtypes.h hlblacklitterman_terminate.c

检查C代码hlblacklitterman.c函数

类型codegen / lib / hlblacklitterman / hlblacklitterman.c
/ * *文件:hlblacklitterman.c * * matlab编码器版本:5.2 * C / C ++源代码:23-FEB-2021 13:41:14 * // *包括文件* / #include“hlblacklitterman.h”#包括“inv.h”#include“pinv.h”#include“rt_nonfinite.h”/ *函数定义* / / * * hlblacklitterman *此功能执行先前*的黑色垃圾混合,并将视图融为一体估计他和垃圾箱中纸张中描述的返回。*输入*Δ-均衡投资组合的风险公差 - 威廉省均衡组合中资产的权重*ΣIigma - 先前的协方差矩阵* Tau  - 在平均值(PI)* P  -  PICK矩阵的先前估计中的不确定性视图 -  Q  - 视图向量返回* Omega  - 视图的差异(对角线)*输出* ER  - 后估计的均值返回* W  - 给予均线估计的未受约束重量*回报的协方差。* lambda  - 每次视图对后估计的影响。* THETA  - 以*后部精度衡量先前和示例信息的份额。* *争论:双倍δ* const双我们[7] * const双sigma [49] * double tau * const ductu p [7] * double q *双omega * double er [7] * double ps [49] * doubleW [7] *双PW [7] * Double * lambda * Double Theta [3] *返回类型:void * / void Hlblacklitterman(双倍Δ,const双Weq [7],const Double Sigma [49],Double Tau, const double P[7], double Q, double Omega, double er[7], double ps[49], double w[7], double pw[7], double *lambda, double theta[3]) { double b_er_tmp[49]; double dv[49]; double posteriorSigma[49]; double ts[49]; double b_y_tmp[7]; double er_tmp[7]; double pi[7]; double unusedExpr[7]; double b; double b_P; double b_b; double d; double y_tmp; int i; int i1; int ps_tmp; /* Reverse optimize and back out the equilibrium returns */ /* This is formula (12) page 6. */ for (i = 0; i < 7; i++) { b = 0.0; for (i1 = 0; i1 < 7; i1++) { b += weq[i1] * sigma[i1 + 7 * i]; } pi[i] = b * delta; } /* We use tau * sigma many places so just compute it once */ for (i = 0; i < 49; i++) { ts[i] = tau * sigma[i]; } /* Compute posterior estimate of the mean */ /* This is a simplified version of formula (8) on page 4. */ y_tmp = 0.0; b_P = 0.0; for (i = 0; i < 7; i++) { b = 0.0; b_b = 0.0; for (i1 = 0; i1 < 7; i1++) { d = P[i1]; b += ts[i + 7 * i1] * d; b_b += d * ts[i1 + 7 * i]; } b_y_tmp[i] = b_b; er_tmp[i] = b; b = P[i]; y_tmp += b_b * b; b_P += b * pi[i]; } b_b = 1.0 / (y_tmp + Omega); b = Q - b_P; for (i = 0; i < 7; i++) { er[i] = pi[i] + er_tmp[i] * b_b * b; } /* We can also do it the long way to illustrate that d1 + d2 = I */ y_tmp = 1.0 / Omega; pinv(P, unusedExpr); /* Compute posterior estimate of the uncertainty in the mean */ /* This is a simplified and combined version of formulas (9) and (15) */ b = 0.0; for (i = 0; i < 7; i++) { b += b_y_tmp[i] * P[i]; } b_b = 1.0 / (b + Omega); for (i = 0; i < 7; i++) { for (i1 = 0; i1 < 7; i1++) { b_er_tmp[i1 + 7 * i] = er_tmp[i1] * b_b * P[i]; } } for (i = 0; i < 7; i++) { for (i1 = 0; i1 < 7; i1++) { b = 0.0; for (ps_tmp = 0; ps_tmp < 7; ps_tmp++) { b += b_er_tmp[i + 7 * ps_tmp] * ts[ps_tmp + 7 * i1]; } ps_tmp = i + 7 * i1; ps[ps_tmp] = ts[ps_tmp] - b; } } for (i = 0; i < 49; i++) { posteriorSigma[i] = sigma[i] + ps[i]; } /* Compute the share of the posterior precision from prior and views, */ /* then for each individual view so we can compare it with lambda */ inv(ts, dv); for (i = 0; i < 7; i++) { for (i1 = 0; i1 < 7; i1++) { b = 0.0; for (ps_tmp = 0; ps_tmp < 7; ps_tmp++) { b += dv[i + 7 * ps_tmp] * ps[ps_tmp + 7 * i1]; } ts[i + 7 * i1] = b; } } b = 0.0; for (ps_tmp = 0; ps_tmp < 7; ps_tmp++) { b += ts[ps_tmp + 7 * ps_tmp]; } theta[0] = b / 7.0; for (i = 0; i < 7; i++) { for (i1 = 0; i1 < 7; i1++) { b_er_tmp[i1 + 7 * i] = P[i1] * y_tmp * P[i]; } } for (i = 0; i < 7; i++) { for (i1 = 0; i1 < 7; i1++) { b = 0.0; for (ps_tmp = 0; ps_tmp < 7; ps_tmp++) { b += b_er_tmp[i + 7 * ps_tmp] * ps[ps_tmp + 7 * i1]; } ts[i + 7 * i1] = b; } } b = 0.0; for (ps_tmp = 0; ps_tmp < 7; ps_tmp++) { b += ts[ps_tmp + 7 * ps_tmp]; } theta[1] = b / 7.0; for (i = 0; i < 7; i++) { for (i1 = 0; i1 < 7; i1++) { b_er_tmp[i1 + 7 * i] = P[i1] * y_tmp * P[i]; } } for (i = 0; i < 7; i++) { for (i1 = 0; i1 < 7; i1++) { b = 0.0; for (ps_tmp = 0; ps_tmp < 7; ps_tmp++) { b += b_er_tmp[i + 7 * ps_tmp] * ps[ps_tmp + 7 * i1]; } ts[i + 7 * i1] = b; } } b = 0.0; for (ps_tmp = 0; ps_tmp < 7; ps_tmp++) { b += ts[ps_tmp + 7 * ps_tmp]; } theta[2] = b / 7.0; /* Compute posterior weights based solely on changed covariance */ for (i = 0; i < 49; i++) { b_er_tmp[i] = delta * posteriorSigma[i]; } inv(b_er_tmp, dv); for (i = 0; i < 7; i++) { b = 0.0; for (i1 = 0; i1 < 7; i1++) { b += er[i1] * dv[i1 + 7 * i]; } w[i] = b; } /* Compute posterior weights based on uncertainty in mean and covariance */ for (i = 0; i < 49; i++) { posteriorSigma[i] *= delta; } inv(posteriorSigma, dv); for (i = 0; i < 7; i++) { b = 0.0; for (i1 = 0; i1 < 7; i1++) { b += pi[i1] * dv[i1 + 7 * i]; } pw[i] = b; } /* Compute lambda value */ /* We solve for lambda from formula (17) page 7, rather than formula (18) */ /* just because it is less to type, and we've already computed w*. */ pinv(P, er_tmp); *lambda = 0.0; for (ps_tmp = 0; ps_tmp < 7; ps_tmp++) { *lambda += er_tmp[ps_tmp] * (w[ps_tmp] * (tau + 1.0) - weq[ps_tmp]); } } /* * File trailer for hlblacklitterman.c * * [EOF] */