Hi,
The code posted yesterday is not right because I did not consider constrain(sum of these proportional =1) when to calculated Efficient Frontier.
Now The code has been updated.
Try the following code .
You need to change 'r' to be small enough to make your model convergency.
do r=0 to 0.04 by 0.001; /*expect return of portfolio*/
Hi. That long time ago, my memory is almost faded away. As I said I just simulate lots and lots of portfolios ,NOT actually calculated Efficient Frontier. If you want it you need solve many optimal problems.
Here is an example:
%let n=20;
proc iml;
/* the number of assets */
n=&n.;
/* riskless rate - Government's bond rate */
f=0.02 ;
/* Start Calculated */
/* two assets and populate data */
asset=j(1000,n,.);
call randseed(1234);
call randgen(asset,'normal');
/* the expect return of two assets (mean) */
return=asset[:,];
/* the variance and covariance of two assets */
cov=cov(asset);
/* p[1] is expect return of porfolio
p[2] is variance of porfolio */
p=j(1,2,.);
/* the tangency portfolio */
start max_slope(x) global(f,p,cov,return);
p[1]=(return#x)[+];
p[2]=x*cov*x`;
/*riskless rate's variance is zero*/
k=(p[1]-f)/p[2];
return (k);
finish;
ods output IterHist=IterHist;
con=repeat({0,1,1},1,n)||{. .,. .,0 1}; /*<---- sum of these proportional =1 */
x=j(1,n,1/n);
optn={1 3};
call nlptr(xres,rc,"max_slope",x,optn,con);
quit;
/************************************/
/************************************/
/************************************/
/************************************/
/* Test if it is tangency portfolio */
/* Take two assets above for example*/
data _null_;
set IterHist;
call symputx('k',OptCrit);
call symputx('f','0.02');
run;
proc iml;
/* The same code as above. Start */
n=&n.;
f=0.02 ;
asset=j(1000,n,.);
call randseed(1234);
call randgen(asset,'normal');
return=asset[:,];
cov=cov(asset);
/* The same code as above. End*/
start min_variance(x) global(cov);
return (x*cov*x`);
finish;
x=j(1,n,1/n);
optn={0 1 0.001};
do r=0 to 0.04 by 0.001; /*expect return of portfolio*/
con=(repeat({0,1,1},1,n)||{. .,. .,0 1})//(return||0||r);
call nlpnrr(rc,xres,"min_variance",x,optn,con) ;
r_cov=r_cov//(r||xres*cov*xres`);
end;
create test from r_cov[c={return variance}];
append from r_cov;
close;
quit;
ods graphics/reset;
proc sgplot data=test;
series x=variance y=return/ lineattrs=(thickness=2) legendlabel='Portfolio' curvelabel='Efficient Frontier';
lineparm x=0 y=&f slope=&k/ legendlabel='Tangency Portfolio' lineattrs=graphdata2(thickness=2);
refline &f / axis=y;
xaxis label='Portfolio Variance';
yaxis label='Portfolio Return';
run;
/* Bingo !!!! */
/************************************/
/************************************/
/************************************/
/************************************/
Actually it is a Quadratic Programming. You could solve this mean-variance model by SAS/IML builded-in functions : CALL LCP() or CALL QPSOLVE() or CALL NLPQUA()
https://blogs.sas.com/content/iml/2024/07/24/new-quadratic-optimization.html
https://blogs.sas.com/content/iml/2024/07/15/isotonic-regression.html
... View more