Examples / PORTFOLIO.RPF |
PORTFOLIO.RPF uses LQPROG to do various portfolio optimization calculations. It analyzes monthly returns on a portfolio of five stocks.
This computes the covariance matrix of returns into OMEGA and the means (which are computed as a side-effect of VCV) into MU.
vcv(center,matrix=omega)
# mobil ibm weyer citcrp
*
compute n=%nvar
compute mu=%meanv
This uses LQPROG to compute the minimum variance portfolio, and uses the weights to compute the mean return for that. If you want to allow short positions, add the NNEG=0 option to LQPROG.
compute [rect] ones=%fill(1,n,1.0)
lqprog(q=omega,a=ones,b=1.0,equalities=1) x
compute minr=%dot(x,mu)
This part finds the minimum variance portfolio with the different expected returns (across the grid in ERETS). This uses @GRIDSERIES to set up a grid (and a parallel series for the computed standard deviations):
@gridseries(from=minr,to=maxr,n=100,pts=ngrid) erets
set srets 1 ngrid = 0.0
Note—the problem being solved by LQPROG is to minimize \((1/2){\bf{x'Qx}}\) subject to the constraints. To get the variance itself, we need to multiply the optimized value by 2. (What's actually saved and later graphed is the standard deviation). The LQPROG now has two equality constraints: weights sum to one, and the weights times means sum to the target return. The ~~ operator is used to "glue" together the constraint matrices.
do t=1,ngrid
lqprog(noprint,q=omega,a=ones~~tr(mu),b=1.0~~erets(t),equal=2)
compute srets(t)=sqrt(2.0*%funcval)
end do t
scatter(style=lines,$
header="Efficient Frontier w/o Risk-Free Asset",$
vlabel="Expected Return",$
hlabel="Sigma")
# srets erets
This does the calculation with a risk-free asset (which was included in the data set). There's no longer a constraint that the weights on the portfolio sum to one. Instead, the expected return constraint is altered to weights * (mu-Rf) = target return - Rf.
stats(noprint) rkfree
compute rf=%mean
set sretsrf 1 ngrid = 0.0
compute [rect] arf=tr(mu)-rf
do t=1,ngrid
lqprog(noprint,q=omega,a=arf,b=erets(t)-rf,equalities=1) x
compute sretsrf(t)=sqrt(2.0*%funcval)
end do t
*
scatter(style=lines,$
header="Efficient Frontier with Risk-Free Asset",$
vlabel="Expected Return",$
hlabel="Sigma") 2
# srets erets
# sretsrf erets
Full Program
open data berndt.xls
calendar(m) 1978
data(format=xls,org=columns) 1978:1 1987:12 mobil ibm weyer citcrp market rkfree
*
* Compute the covariance matrix of returns into omega. Save the means as
* mu.
*
vcv(center,matrix=omega)
# mobil ibm weyer citcrp
*
compute n=%nvar
compute mu=%meanv
compute [rect] ones=%fill(1,n,1.0)
*
* Compute the minimum variance portfolio, and its expected return. All
* the analysis is constraining portfolios to non-negative weights. If
* you want to allow short positions, add the NNEG=0 option to LQPROG.
*
lqprog(q=omega,a=ones,b=1.0,equalities=1) x
compute minr=%dot(x,mu)
*
* Choose as upper limit the highest expected return.
*
compute maxr=%maxvalue(mu)
*
* Create a grid series for expected values running from minr to maxr
*
@gridseries(from=minr,to=maxr,n=100,pts=ngrid) erets
set srets 1 ngrid = 0.0
*
* Find the minimum variance portfolio with the expected return erets(t).
* Note - the problem being solved is to min .5 x'Qx subject to the
* constraints. To get the variance (rather than .5 variance), we need to
* multiply the optimized value by 2.
*
do t=1,ngrid
lqprog(noprint,q=omega,a=ones~~tr(mu),b=1.0~~erets(t),equal=2)
compute srets(t)=sqrt(2.0*%funcval)
end do t
scatter(style=lines,$
header="Efficient Frontier w/o Risk-Free Asset",$
vlabel="Expected Return",$
hlabel="Sigma")
# srets erets
*
* With riskfree asset. There's no longer a constraint that the weights
* on the portfolio sum to one. Instead, the expected return constraint
* is altered to weights * (mu-Rf) = target return - Rf.
*
stats(noprint) rkfree
compute rf=%mean
set sretsrf 1 ngrid = 0.0
compute [rect] arf=tr(mu)-rf
do t=1,ngrid
lqprog(noprint,q=omega,a=arf,b=erets(t)-rf,equalities=1) x
compute sretsrf(t)=sqrt(2.0*%funcval)
end do t
*
scatter(style=lines,$
header="Efficient Frontier with Risk-Free Asset",$
vlabel="Expected Return",$
hlabel="Sigma") 2
# srets erets
# sretsrf erets
Output
Covariance\Correlation Matrix
MOBIL IBM WEYER CITCRP
MOBIL 0.006395555 0.32120 0.38650 0.31106
IBM 0.001509807 0.003454803 0.49182 0.42370
WEYER 0.002618329 0.002448826 0.007175982 0.54000
CITCRP 0.002005844 0.002008121 0.003688490 0.006501805
QPROG converges at 4 iterations
minimum = 0.00137601
Solution x =
0.2348612493 0.5909593334 0.0136067763 0.1605726410
Lagrange Multipliers
-0.002752013
Graphs
Copyright © 2025 Thomas A. Doan