RATS 10.1
RATS 10.1

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