1
CHAPTER 4
Portfolio Mean-Variance Optimization
4.1. Portfolio Selection
The fundamental goal of portfolio selection is to optimally allocate investments between different
assets by considering the trade-off between risk and return. In this chapter, we discuss the
implementation of a quantitative tool known as Mean-Variance Optimization (MVO) using the matrix
operation in EXCEL and VBA. Consider a portfolio consisting of n assets with prices { S1 , … , Sn }
and quantities { q1 , … , qn }. If it is to be kept for a period of time, the portfolio value at end of period
will be subjected to uncertain asset price changes { S1 , … , Sn }. The potential gain or loss of the
portfolio in this period can be summed up as
SP
n
i 1 qi Si (4.1)
The objective of MVO is to determine the optimal portfolio content within a budget so as to minimize
the risk exposure in this period under an expected growth in value. The idea relies on the correlation
among asset price changes under a stochastic regime for which the statistics can be inferred from
historical data.
It is convenient to rewrite equation (4.1) in terms of asset price returns ri Si /Si over the
investment horizon for which portfolio return rP in this period can be written as a weighted sum of
asset returns in the basket. This gives
rP
n
i 1 wi ri ,
n
i 1 wi 1 (4.2)
where the weight factor wi represents the fraction of the total portfolio budget that will be invested on
the i-th asset. In the stochastic model, uncertain asset returns in (4.2) can all be considered as random
variables parameterized by historical means and variances. Written as their linear combination,
portfolio return can also be considered as a random variable with mean and variance defined through
(4.2) as
P
n
i 1 wi i (4.3)
P
2
n
i 1
n
j 1 wi wj ij (4.4)
where i and i
2
ii denote respectively the mean and variance of individual asset return ri , and ij
for i j denotes the covariance between two different returns ri and rj. Under this framework, the task
of MVO is to determine the optimal portfolio content that minimizes the random variation of the
portfolio return in (4.4) given an expected return in (4.3) and should also be feasible under the
portfolio budget. The variance terms wi
2 i
2
in (4.4) are strictly positive and they are adding up. The
idea of MVO relies on the fact that the covariance terms wi wj ij could possibly be negative and thus
diversify the total portfolio variance.
It is efficient to express equations (4.3) and (4.4) in matrix multiplication and formulate MVO as
the determination of the column vector w that
minimize P
2
w
T
w (4.5)
subject to w
T
P and u
T
w 1
2
where
1
2
12 … 1n
w1 1 21 2
2
… 2n
w , , u ,
wn n
n1 n2 … n
2
The entries in the mean vector and the variance-covariance matrix can presumably be estimated
using historical asset returns over the same horizon as the portfolio. The optimization in (4.5) allows
both long and short positions for which wi can be positive or negative. It can be solved very easily
using the method of Lagrange multipliers and the optimal solution was first worked out by Merton1 as
(4.6)
(4.7)
where A u
T
1 , B
T
1 , and C u
T
1 u. Since the variance-covariance matrix is
symmetric, it can be shown that the two quadratic forms, B and C, and the denominator BC A2 are
all positive. The optimal portfolio mean-variance relation in (4.7) is then strictly convex as shown in
Figure 4.1(a). It is usual to invert (4.7) and present the risk-adverse domain ( P A/C ) of the mean-
variance relation in term of the so-called portfolio efficient frontier as shown in Figure 4.1(b) with the
following optimal relation.
(4.8)
Figure 4.1: (a) Optimal portfolio mean-variance relation with risky assets only, and (b) Portfolio
efficient frontier.
1 See Robert C. Merton, “An analytic deviation of the efficient portfolio frontier”, Journal of Financial and
Quantitative Analysis, Vol. 7, No. 3 (1972) p1851-1872. We first define the Lagrange function L that
incorporates the objective function and the constraints in (4.5) with two multipliers 1 and 2 as
L ½ wT w 1 ( w
T P ) 2 ( u
T w 1 )
The optimal w can be determined through the first order stationary conditions : { L/w1 0, … , L/wn 0 }
in conjunction with the original constraints.
CP
2
2AP B
BC A2
P
2
P (BC A
2)(CP
2
1)
A
C
1
C
(a) P
2
P
Risk-adverse
A/C
1/C
1/√C
A/C
(b)
P
P
Efficient frontier
( CP A )(
1 ) ( B AP )(
1 u)
BC A2
w
3
The above discussion analyzes the case in which all the available assets are risky. We can extend
the analysis to include risk-free cash that provides a guaranteed return 0 over the investment period.
Consider w0 to be the fraction of the total portfolio budget that will be held as cash. Reformulate the
MVO in (4.5) as the determination of the column vector w and w0 that
minimize P
2
w
T
w (4.9)
subject to w
T
w0 0 P and u
T
w w0 1
Again, it can be solved very easily using the method of Lagrange multipliers2 and the optimal
portfolio content is given by
(4.10)
that generates the efficient frontier as shown in Figure (4.2) with the following linear optimal
relation3.
(4.11)
Figure 4.2: Efficient frontier of a portfolio with cash and risky assets.
We have considered so far MVO that allows both long and short positions on the risky assets for
which wi can be positive or negative. Suppose there are short-selling restrictions on the risky assets
due to market constraint or internal policy. In such long-only portfolio, the asset positions wi are all
limited to be non-negative in the optimization. Accordingly, the MVO in (4.9) should be appended
with additional constraints as
minimize P
2
w
T
w (4.12)
subject to w
T
w0 0 P , u
T
w w0 1 , and w1 , … , wn 0
2 Similarly, we can define the Lagrange function L with two multipliers 1 and 2 as
L ½ wT w 1 ( w
T w0 0 P ) 2 ( u
T w w0 1 )
The optimal w and w0 can be determined through the stationary conditions : { L/w0 0, L/w1 0, … ,
L/wn 0 }.
3 We can rewrite the optimal risky content in (4.10) as w (1 w0) ŵ where ŵ (
1 0
1u )/(A 0C).
Along the efficient frontier, we are actually buying or short-selling various units of the so-called market
portfolio { ŵ1, … , ŵn } together with cash holding. For 0 A/C , the cash position w0 can be positive, zero, or
negative through borrowing. For 0 A/C, the cash position is however strictly positive.
P 0 P C0
2
2A0 B
,
0
P
P
Efficient frontier
w0 1
( P 0 )( A 0 C )
C0
2
2A0 B
w
( P 0 )(
1 0
1u )
C0
2
2A0 B
4
It should be noted that the cash position w0 remains unconstrained in (4.12) where it can be positive,
zero, or negative. In principle, (4.12) can be solved using again the method of Lagrange multipliers4.
However, the evaluation of the optimal portfolio content would be non-trivial because of the
inequality constraints in the Kuhn-Tucker conditions.
Markowitz has developed an efficient algorithm5 that allows us to solve the MVO in (4.12) using
simply the optimal result in (4.10). Consider another MVO related to (4.12) for which we delete the
non-negative constraints w1, 2, … , n 0 and instead constrain certain subset of { w1, … , wn }, called the
OUT subset, to be zero. The basic idea in the Markowitz algorithm is that the optimal solution of this
related problem could possibly be a particular solution of the original problem for specific segment of
the efficient frontier. The optimal solution can simply be obtained from (4.10) by modifying the array
entries in { , , u } associated with the OUT subset. If wi is in the OUT subset, we set the i-th row of
both the vectors and u to zero, and also the i-th row and i-th column of the matrix to zero except
the diagonal entry which set to be one.
i 0 , ui 0 (4.13)
i1 , … , in 0 , 1i , … , ni 0 , except ii 1
Suppose { m , m , um } are the modified arrays according to the OUT subset. The optimal solution of
the related problem is then given by
(4.14)
with multipliers
where Am um
T
m
1 m , Bm m
T
m
1 m , and Cm um
T
m
1 um . It is clear in (4.14) that wi 0 inside the
OUT subset. If all wi outside the OUT subset are non-negative for particular value of P, (4.14) could
possibly be a solution of the MVO in (4.12) that also satisfies the Kuhn-Tucker conditions as
L/w0 1 0 2 0 (4.15)
L/wi ( w 1 2 u)i 0 when wi 0 (4.16)
0 when wi 0 , for i 1, … , n
4 Define the Lagrange function H with multipliers { 1 , 2 , 1 , … , n } as
H L 1 w1 … n wn , where L ½ w
T w 1 ( w
T w0 0 P ) 2 ( u
T w w0 1 )
With inequality constraints, the optimal w and w0 can be determined through the Kuhn-Tucker conditions :
L/w0 0 , L/wi i , i 0 , wi 0 , and i wi 0 for i 1, … , n
that can be rewritten as L/w0 0 , L/wi 0 when wi 0 , and L/wi 0 when wi 0 for i 1, … , n.
5 See H.M. Markowitz, G.P. Todd, and W.F. Sharpe, Mean-Variance Analysis in Portfolio Choice and Capital
Markets, Frank J. Fabozzi Associates, 1987.
, w0 1
( P 0 )( Am 0 Cm )
Cm 0
2
2Am 0 Bm
w
( P 0 )( m
1m 0 m
1um )
Cm 0
2
2Am 0 Bm
, 1
( P 0 )
Cm 0
2
2Am 0 Bm
2
0 ( P 0 )
Cm 0
2
2Am 0 Bm
5
It should be noted that L/w0 0 in (4.15) would automatically be satisfied with the multipliers
defined in (4.14). Given portfolio return P 0 , we can determine the optimal portfolio content by
solving the MVO in (4.12) through the Markowitz algorithm as
(1) Define an OUT subset and construct the modified arrays { m , m , um } according to (4.13).
(2) Check that all the entries of w in (4.14) are non-negative. If so, proceed to step (3). If this is not
the case, return to step (1) and try another OUT subset.
(3) Check that condition (4.16) has been satisfied. If so, w0 and w defined in (4.14) will be an optimal
solution given portfolio return P. Otherwise, return to step (1) and try another OUT subset.
In step (1), the size of the OUT subset can be chosen from Nout 0 to Nout n 1. When Nout n,
there is only one OUT subset namely the entire risky content { w1, … , wn }. The algorithm will not
work as well in this case as the denominator in (4.14) vanishes with m and um being zero vectors.
However, this corresponds to the trivial portfolio content with w 0 and w0 1. The algorithm will
guarantee to find a solution before we exhaust the list of all OUT subsets. Also, the optimal portfolio
content is unique given return. We should quit the routine once we obtain a solution.
4.2. EXCEL Implementation
It is always convenient to separate the raw data from the actual calculations using different
worksheets defined as6
dayclose Historical daily closing prices of all risky assets to be considered.
return Historical price returns generated through “dayclose” for specific time horizon.
MVO Actual calculations of the mean-variance optimization based on “return”.
Figure 4.3 depicts the layout of the worksheet “dayclose” with historical daily closing prices of 35
commonly traded commodities from year 1998 to 2005. Sequences of closing prices are recorded one
column per asset starting from column B onward with the corresponding timestamp given by column
A. In each column, the top cell records the asset name with its ticker symbol in the following cell. For
example, column B records the daily closing prices of Crude Oil with ticker symbol being CL.
Figure 4.3: The layout of the worksheet “dayclose” with daily closing prices.
Figure 4.4 displays the worksheet “return” that contains the historical price returns of the assets.
They are generated dynamically using the raw data in “dayclose” and according to the investment
horizon defined in cell K16 (named as horizon) of worksheet “MVO”. Again, return sequences are
6 Refer to mean_variance_opt.xls.
6
arranged one column per asset starting from column A onward with the corresponding ticker symbol
defined in the top cell. Such labeling row can be constructed through a direct mapping from
“dayclose” using the common expression A1 dayclose!B2 along the row. The investment horizon
should be defined in number of days. Suppose, for example, it is taken to be five days (horizon 5).
The cell A2 should correspond to the price return of CL with opening price dayclose!B3 and closing
price dayclose!B8 five days later. In the same way, the following cell A3 should correspond to the
price return from dayclose!B8 to dayclose!B13 in the subsequent five days. In general, this can be
done very easily using the OFFSET function with the leftmost corner cell dayclose!$A$3 being the
reference location in worksheet “dayclose”. In each column of worksheet “return”, price returns in
each cell can be calculated by identifying the opening and closing prices through row offset from the
reference location according to its row number ROW() as
opening price OFFSET( dayclose!$A$3, ( ROW() 2 ) horizon , COLUMN() )
closing price OFFSET( dayclose!$A$3, ( ROW() 1 ) horizon , COLUMN() )
price return ( closing price opening price ) / opening price
The column number COLUMN() will provide a column offset from the reference location to match
up the ticker symbol in the two worksheets. Running down the row of “return”, price returns should
be calculated until the location of the closing price has exceeded the data range of “dayclose”. It
happens when closing price is pointing to a blank cell thereafter, and where we simply insert a blank
cell in “return”. The following expression can be applied to every columns of “return” with ticker
symbol:
IF( OFFSET( dayclose!$A$3, ( ROW() 1 ) horizon , COLUMN() ) “” , “” ,
( OFFSET( dayclose!$A$3, ( ROW() 1 ) horizon , COLUMN() )
OFFSET( dayclose!$A$3, ( ROW() 2 ) horizon , COLUMN() ) )
/ OFFSET( dayclose!$A$3, ( ROW() 2 ) horizon , COLUMN() ) )
Figure 4.4: The layout of the worksheet “return” with price returns over specific investment horizon.
In worksheet “MVO”, we first construct the variance-covariance matrix using the asset price
returns in “return”. Figure 4.5 depicts the layout of the matrix with user-defined portfolio contents. As
shown in the figure, the number of assets to be included in the portfolio is arbitrary with the maximum
size limited to ten. The choice of asset can be specified through the cells J3:S3 by entering their ticker
symbols. The total number of assets in the portfolio is given by K15 COUNTA( J3:S3 ) that counts
the number of non-empty cells in this array. The adjacent cells J4:S4 will identify the corresponding
column location of data in worksheet “return” to facilitate calculation of the matrix. For an unused
blank cell in J3:S3, the adjacent cell will also be blank in J4:S4. The following expression can be used
to define J4 and apply to all other cells in J4:S4 :
7
J4 IF( J3 “” , “” , MATCH( J3 , return!1:1 , 0 ) )
In Figure 4.5, the ticker symbol of J3 is defined as HG, the above function will search for this item in
array return!1:1 ( row 1 of “return”) and report in J4 its relative position (the sixth column) in this
array. We can use the column locations acquired in cells J4:S4 to construct the variance-covariance
matrix defined in cells J5:S14 (named as vcmatrix). We first repeat the same sequence vertically in
cells I5:I14 based on the common expression I5 IF( J4 “” , “” , J4 ). Thus, each matrix entry ij
will associate with the target column locations of two assets reading off from I5:I14 ( for i 1, 2, … )
and J4:S4 ( for j 1, 2, … ). For example, the entry in J5 has target locations given by I5 and J4. The
corresponding return data to be included in the covariance calculation can be identified using the
OFFSET function with the cell return!$A$2 in leftmost column of “return” being the reference
location.
COVAR( OFFSET( return!$A$2 , 0 , $I5 1 , nsample ) ,
OFFSET( return!$A$2 , 0 , J$4 1 , nsample ) ) (4.17)
For both target locations, the row and column offsets from the reference location aim at the leading
entry of the data set, the height parameter (named as nsample) then defines the downward range to be
included in the calculation. The height parameter is simply the size of the return data given an
investment horizon. It is defined in N16 COUNT( return!A:A ) by counting the number of numeric
cells in column A of “return”. If there are blank cells in J4:S4 (and so I5:I14), the variance-covariance
matrix will have redundant columns (and rows) relative to the unused cells. With respect to such
redundancy, the matrix should be augmented with zero columns (and zero rows) except an one at
diagonal entries. We can use the following formula to define J5 and all other matrix entries:
J5 IF( OR( $I5 “” , J$4 “” ) ,
IF( ROW() ROW( $J$5 ) COLUMN() COLUMN( $J$5 ) , 1 , 0 ) ,
COVAR( OFFSET( return!$A$2 , 0 , $I5 1 , nsample ) ,
OFFSET( return!$A$2 , 0 , J$4 1 , nsample ) ) )
Figure 4.5: The layout of the variance-covariance matrix in worksheet “MVO”.
As shown in Figure 4.6, the mean vector is defined in C5:C14 (named as mvec) of worksheet
“MVO”. Similar to (4.17), it can be constructed with reference to the target locations given by I5:I14.
For example, the mean return in C5 can be calculated according to the target location in I5 as
AVERAGE( OFFSET( return!$A$2 , 0 , $I5 1 , nsample ) )
8
Again, the mean vector will have zero redundant entries if there are blank cells in I5:I14. This is also
true for the u vector defined in B5:B14 (named as uvec). The following expressions can be used to
define the mean vector and the u vector, respectively, as
C5 IF( $I5 “” , 0 , AVERAGE( OFFSET( return!$A$2 , 0 , $I5 1 , nsample ) ) )
B5 IF( $I5 “” , 0 , 1 )
Figure 4.6: The layout of the optimal output in worksheet “MVO”.
Consider first the MVO problem in (4.5) that allows both long and short positions in risky assets.
As shown in Figure 4.5, we have evaluated the factors A, B, and C in cells K17 (named as Avalue),
K18 (named as Bvalue), and K19 (named as Cvalue), respectively, through EXCEL matrix operations
as
K17 = MMULT( TRANSPOSE( uvec ) , MMULT( MINVERSE( vcmatrix ) , mvec ) )
K18 = MMULT( TRANSPOSE( mvec ) , MMULT( MINVERSE( vcmatrix ) , mvec ) )
K19 = MMULT( TRANSPOSE( uvec ) , MMULT( MINVERSE( vcmatrix ) , uvec ) )
In Figure 4.6, the expected portfolio return P is defined in D18 (named as mport) by scaling the
choice of daily rate in C18 with the investment horizon as D18 C18horizon. The optimal portfolio
content w in (4.6) can be determined in cells D5:D14 using the formula
{ D5:D14 ( ( Cvalue mport Avalue ) MMULT( MINVERSE( vcmatrix ) , mvec )
( Bvalue Avalue mport ) MMULT( MINVERSE( vcmatrix ) , uvec ) )
/ ( Bvalue Cvalue Avalue^2 ) }
The minimized portfolio variance P
2
can be calculated in D19 based on the optimal content as
D19 MMULT( TRANSPOSE( D5:D14 ) , MMULT( vcmatrix , D5:D14 ) )
Consider the MVO problem in (4.9) with the inclusion of cash. In Figure 4.6, the risk-free return
0 is defined in D17 C17horizon (named as riskfree) by scaling the daily rate in C17. The optimal
portfolio content w and cash w0 in (4.10) can be determined in cells E5:E14 and E15, respectively,
using the formula
9
{ E5:E14 ( mport riskfree ) ( MMULT( MINVERSE( vcmatrix ) , mvec )
riskfree MMULT( MINVERSE( vcmatrix ) , uvec ) )
/ ( Cvalue riskfree^2 2 Avalue riskfree Bvalue ) }
E15 1 ( mport riskfree ) ( Avalue riskfree Cvalue )
/ ( Cvalue riskfree^2 2 Avalue riskfree Bvalue )
As before, the minimized portfolio variance can also be calculated in E19 based on the optimal
content.
Consider now the MVO problem in (4.12) with short-selling restrictions on risky assets. We defer
our discussion on the implementation of the Markowitz algorithm to section 4.3 with the use of VBA.
Here, we consider solving this problem using EXCEL SOLVER despite there are critical issues on
initializing the algorithm. In Figure 4.6, the portfolio content w to be optimized is defined in cells
G5:G14. The corresponding cash position w0 in G15 can be related to this content through the budget
constraint w0 1 u
T
w in (4.12) as
G15 1 MMULT( TRANSPOSE( uvec ) , G5:G14 )
In G18 and G19, we explicitly evaluate the expected return w
T
w0 0 and variance w
T
w of the
portfolio, respectively, relative to this content as
G18 MMULT( TRANSPOSE( G5:G14 ) , mvec ) G15 riskfree
G19 MMULT( TRANSPOSE( G5:G14 ) , MMULT( vcmatrix , G5:G14 ) )
In the Solver Parameters screen as shown in Figure 4.7, we set the Target Cells to be the portfolio
variance in G19 and check Equal To as Min for minimizing. We take in the By Changing Cells the
portfolio content in cells G5:G14 and include in the Subject to the Constraints field the condition
that the so-evaluated portfolio return in G18 must equal the prescribed value mport in D18. In the
Solver Options screen as shown in Figure 4.8, we check Assume Non-Negative that imposes the
non-negative constraints in (4.12) on the portfolio content specified in the By Changing Cells. It is
sufficient to consider in Precision the required precision of 108 for the algorithm and limits the
number of iterations within 20. To start off the search algorithm, we need to provide initial values for
G5:G14 as close to the solution as possible. A proper choice would be a cash portfolio with no risky
assets { w1 0, … , wn 0 }. However, there is no guarantee of finding the correct optimal solution.
Figure 4.7: Solver Parameters screen.
10
Figure 4.8: Solver Options screen.
4.3. EXCEL Plus VBA Implementation
An effective and reliable way to solve the MVO problem in (4.12) is to implement the Markowitz
algorithm as discussed in section 4.1 using VBA. It will guarantee to find the correct optimal solution
that is unique given portfolio return. The idea is to examine all possible OUT subsets and identify the
particular case that generates the optimal solution of the original problem. The size of the OUT subset
can run from Nout 0 to Nout n 1. For each Nout , there are Nc ( equals n choose Nout ) OUT subsets
with different combinations:
Nout OUT subsets Nc
0 { } 1
1 { w1 }, { w2 }, … , { wn } n
2 { w1 , w2 }, { w1 , w3 }, … , { w1 , wn }, { w2 , w3 }, … , { w2 , wn }, … , { wn 1 , wn } ½n(n 1)
n 1 { w2 , w3 , … , wn }, { w1 , w3 , … , wn }, … , { w1 , w2 , … , wn 1 } n
Among all possible OUT subsets above, there is a unique combination for which the corresponding
optimal content w given by (4.14) will be non-negative and satisfies the Kuhn-Tucker conditions in
(4.16).
We first develop a routine called GetOutSubset( ) capable of generating all OUT subsets given its
size Nout k. Consider the array Ik( L, 1: k ) that provides in ascending order the pointers to all
elements in different OUT subsets labeling through L 1, …, Nc(k). When k 2, for example, we
have I2( 1, 1 ) 1 and I2( 1, 2 ) 2 that define the first OUT subset { w1 , w2 }. Pointer arrays of size k
can be generated by appending every pointer array of size k 1 with an additional entry of higher
value. Given pointer array Ik 1( l, 1: k 1 ) of size k 1, we can generate several pointer arrays of
size k (labeled consecutively as L l, l 1, …); each with additional entry of separate value greater
than the last entry in the given array:
h …
Ik 1( l, 1: k 1 ) h 1
Ik( l, 1: k )
h 2
n
Ik( l + 1, 1: k )
11
In this way, the entire set of pointer arrays Ik( L, 1: k ) for L 1, …, Nc(k) can be generated iteratively
by considering every Ik 1( L, 1: k 1 ) for L 1, …, Nc(k 1). The pseudo code of GetOutSubset( )
is given by Code 4.1 which performs such tasks. As input, the routine reads in all pointer arrays for
size k 1 and the number of combinations. As output, it generates the arrays for size k and updates the
number of combinations. The iteration should start off from k 1 with Nc(1) n pointer arrays,
namely, I1( 1, 1 ) 1, I1( 2, 1 ) 2, … , and I1( n, 1 ) n. The VBA code of GetOutSubset( ) is given
by Code 4.2. Note that “nmax” and “Ncmax” are parameters that configure the maximum possible
size of n and Nc, respectively, in the module. In worksheet “MVO”, the number of assets to be
included in the portfolio is limited below ten. We should set nmax 10, and the maximum number of
OUT subsets should correspondingly be Ncmax 252 (10 choose 5).
__________________________________________________________________________________
GetOutSubset( n , k , Nc , I( 1 : Nc , 1 : k ) )
l 0
# input Nc and I for size k 1, and consider every input array
For( L 1 to Nc ) {
# for particular array I, generate several Inew for size k with consecutive labeling
For( j I( L, k 1 ) 1 to n ) { l = l 1
For( i = 1 to k 1 ){ Inew( l, i ) I( L, i ) }
Inew( l, k ) j }
}
# return Inew as I and update Nc
For( L 1 to l ) { For( i 1 to k ){ I( L , i ) Inew( L , i ) } }
Nc l
__________________________________________________________________________________
Code 4.1: Pseudo code of the GetOutSubset( ) routine.
__________________________________________________________________________________
Sub GetOutSubset(n As Integer, k As Integer, ByRef Nc As Integer, ByRef Iout() As Integer)
Dim lcount As Integer, L As Integer, Lprime As Integer
Dim i As Integer, j As Integer
Dim Inew(1 To Ncmax, 1 To nmax) As Integer
lcount = 0
For Lprime = 1 To Nc
For j = Iout(Lprime, k – 1) + 1 To n
lcount = lcount + 1
For i = 1 To k – 1
Inew(lcount, i) = Iout(Lprime, i)
Next i
Inew(lcount, k) = j
Next j
Next Lprime
For L = 1 To lcount
For i = 1 To k
Iout(L, i) = Inew(L, i)
Next i
Next L
Nc = lcount
End Sub
__________________________________________________________________________________
Code 4.2: VBA code of the GetOutSubset( ) routine.
12
We now want to develop a routine called Markowitz( ) that considers every OUT subset generated
from GetOutSubset( ) and performs the checking in steps 1-3 as stated at end of section 4.1. The
pseudo code of Markowitz( ) is given by Code 4.3. As input, it reads in the total number of risky
assets n, the data arrays { , , u }, the expected portfolio return P, and the risk-free return 0. As
output, it returns the optimal portfolio content w and cash position w0. To examine all possible OUT
subsets, we have considered in the outer loop the values of Nout from 0 to n 1. For each Nout, we
generate the entire OUT subsets and perform the checking on every combination in the inner loop of
L. The checking will proceed to higher values of Nout until an optimal solution has been identified
where the procedure will be stopped immediately.
For Nout 0, there is Nc(0) 1 OUT subset { } with no modification on the entries in { , , u }.
For Nout 1, the OUT subsets are generated iteratively through GetOutSubset( ) starting off from Nout
1 with Nc(1) n subsets as defined above. For each OUT subset, the modified arrays { m , m , um }
will be constructed according to the generated pointer array, and the portfolio content defined in
(4.14) will also be calculated. The checking of non-negative and Kuhn-Tucker conditions for such
portfolio content will subsequently be conducted.
It should be noted that the denominator Dm Cm 0
2
2Am 0 Bm in (4.14) is strictly positive.
However, it could possibly be negative due to floating point precision that renders the sign of (4.14) to
be misidentified. Under double precision, a real number will only be quoted up to 15 decimal places,
it is therefore essential to adjust the denominator by a floating precision of 1014. The same factor
should also be used in checking whether a real number x is negative (x ), positive (x ), or zero
(|x| ). Using the first “Next L”, we skip those OUT subsets with negative portfolio content in (4.14)
if wi for either one component of w. Then, for the Kuhn-Tucker conditions in (4.16), we skip
again using the second “Next L” if neither ( i ) ( |wi| ) or ( |i| ) ( wi ) is true ( i.e.
testflag .False.) for either one component of w and ( w 1 2 u). It runs through all L and
proceeds to higher values of Nout. If an OUT subset has not been filtered out by these two exit
conditions, the corresponding portfolio content in (4.14) will be the optimal solution of the MVO in
(4.12). The entire procedure will be stopped immediately by “Exit Nout” that exits two nested loops.
__________________________________________________________________________________
Markowitz( n , (1 : n ) , u(1 : n) , (1 : n , 1 : n ) , P , 0 , w(1 : n) , w0 )
1 1014
For ( Nout 0 to n 1 ) {
# generate the OUT subsets
If( Nout 0 ) then
Nc 1
elseif( Nout 1) then
Nc n
For ( L 1 to Nc ) { I( L , 1 ) L }
else
Call GetOutSubset( n , Nout , Nc , I( 1 : Nc , 1 : Nout ) )
endif
For ( L 1 to Nc ) {
# construct the modified arrays according to (4.13)
For ( i 1 to n ) { m( i ) ( i ) , um( i ) u( i )
13
For ( j 1 to n ) do{ m( i , j ) ( i , j ) } }
For ( k 1 to Nout ) { i I( L , k )
m( i ) 0 , um( i ) 0
For ( j 1 to n ) { m( i , j ) 0 , m( j , i ) 0 }
m( i , i ) 1 }
# calculate Am, Bm, and Cm
Am u
T
m( 1 : n ) m
1( 1 : n , 1 : n ) m( 1 : n )
Bm
T
m( 1 : n ) m
1( 1 : n , 1 : n ) m( 1 : n )
Cm u
T
m( 1 : n ) m
1( 1 : n , 1 : n ) um( 1 : n )
# calculate the portfolio content defined in (4.14)
Dm Cm 0
2
2Am 0 Bm
1 ( P 0 ) / Dm , 2 0 ( P 0 ) / Dm
w( 1 : n ) 1 m
1( 1 : n , 1 : n ) m( 1 : n ) 2 m
1( 1 : n , 1 : n ) um( 1 : n )
w0 1 1 ( Am 0 Cm )
# check that all the entries of w in (4.14) are non-negative
For ( i 1 to n ) { If( w( i ) ) { Next L } }
# check that the KKT condition (4.16) has been satisfied
( 1 : n ) ( 1 : n , 1 : n ) w( 1 : n ) 1 ( 1 : n ) 2 u( 1 : n )
For ( i 1 to n ) { testFlag OR( AND( ABS( ( i ) ) , w( i ) ) ,
AND( ( i ) , ABS( w( i ) ) ) )
If ( .NOT. testFlag ) { Next L } }
Exit Nout
} }
__________________________________________________________________________________
Code 4.3: Pseudo code of the Markowitz( ) routine.
The VBA code of Markowitz( ) is given by Code 4.4. For the calculations of Am, Bm and Cm , we
have used the routine SolveAxb( ) (see Code 3.4) to first calculate the vectors m
1m and m
1um. The
matrix multiplications with the transposed vectors u
T
m and
T
m can then be performed very easily
through the rule x
T
y
n
i 1 xi yi for two (n 1) vectors. In addition, the portfolio content w in (4.14)
can also be calculated immediately using the same results. Notice that the vector L/w in (4.16)
has been determined by directly applying the rule for matrix multiplication and addition as
i
n
k 1 ik wk 1 i 2 ui , for i 1, 2, …, n
To exit a nested loop during the checking of non-negative w and the KKT condition, we use “GoTo
nextL” and label the “Next L” statement in the coding as “nextL”. To terminate the entire procedure
once the optimal solution has been found, we exit two nested loops using “GoTo exitNout” for which
we label the line immediately after “Next Nout” as “exitNout”.
We will use the same spreadsheet design in Figures 4.5 and 4.6 for this VBA implementation. The
main VBA routine MVO( ) can be invoked through the “Markowitz” button in the spreadsheet as
shown in Figure 4.6. In Code 4.5, we have divided the MVO( ) routine into three parts handling the
data input, the core Markowitz algorithm, and the output. As input, it reads in the total number of
risky assets n in cell K15, the expected portfolio return P in cell D18, and the risk-free return 0 in
14
cell D17. It also reads in the data arrays { , , u } according to the size of n with the use of the
OFFSET function relative to the cells J5, C5, and B5, respectively. As output, it returns the optimal
portfolio content and cash position that display in cells F5:F14 and F15, respectively. It should be
noted that if n is less than nmax 10, the additional portfolio contents in F5:F14 will always be zero
in the output.
__________________________________________________________________________________
Sub Markowitz(n As Integer, mvec() As Double, uvec() As Double, vcmatrix() As Double, mport As Double, _
riskfree As Double, ByRef wvec() As Double, ByRef w0 As Double)
Dim Nout As Integer, Nc As Integer
Dim Iout(1 To Ncmax, 1 To nmax) As Integer
Dim L As Integer, i As Integer, j As Integer, k As Integer
Dim mvecm(1 To nmax) As Double
Dim uvecm(1 To nmax) As Double
Dim vcmatrixm(1 To nmax, 1 To nmax) As Double
Dim etavec(1 To nmax) As Double
Dim tempvec1(1 To nmax) As Double
Dim tempvec2(1 To nmax) As Double
Dim Am As Double, Bm As Double, Cm As Double, Dm As Double
Dim lambda1 As Double, lambda2 As Double
Dim testFlag As Boolean
For Nout = 0 To n – 1
‘generate the OUT subsets
If (Nout = 0) Then
Nc = 1
ElseIf (Nout = 1) Then
Nc = n
For L = 1 To Nc: Iout(L, 1) = L: Next L
Else
Call GetOutSubset(n, Nout, Nc, Iout)
End If
For L = 1 To Nc
‘construct the modified arrays
For i = 1 To n
mvecm(i) = mvec(i)
uvecm(i) = uvec(i)
For j = 1 To n: vcmatrixm(i, j) = vcmatrix(i, j): Next j
Next i
For k = 1 To Nout
i = Iout(L, k)
mvecm(i) = 0
uvecm(i) = 0
For j = 1 To n
vcmatrixm(i, j) = 0
vcmatrixm(j, i) = 0
Next j
vcmatrixm(i, i) = 1
Next k
‘calculate Am, Bm, and Cm
Call SolveAxb(vcmatrixm, mvecm, tempvec1, n, 1, 1, 1)
Call SolveAxb(vcmatrixm, uvecm, tempvec2, n, 1, 1, 1)
Am = 0
Bm = 0
Cm = 0
For i = 1 To n
Am = Am + uvecm(i) * tempvec1(i)
Bm = Bm + mvecm(i) * tempvec1(i)
Cm = Cm + uvecm(i) * tempvec2(i)
Next i
‘calculate the portfolio content
Dm = Cm * riskfree ^ 2 – 2 * Am * riskfree + Bm + eps
lambda1 = (mport – riskfree) / Dm
lambda2 = -riskfree * (mport – riskfree) / Dm
For i = 1 To n: wvec(i) = lambda1 * tempvec1(i) + lambda2 * tempvec2(i): Next i
15
w0 = 1 – lambda1 * (Am – riskfree * Cm)
‘check that the portfolio content are non-negative
For i = 1 To n
If (wvec(i) < -eps) Then GoTo nextL Next i 'checking the KKT condition For i = 1 To n tempvec1(i) = 0 For j = 1 To n: tempvec1(i) = tempvec1(i) + vcmatrix(i, j) * wvec(j): Next j etavec(i) = tempvec1(i) - lambda1 * mvec(i) - lambda2 * uvec(i) Next i For i = 1 To n testFlag = (Abs(etavec(i)) <= eps And wvec(i) >= – eps) Or (etavec(i) > eps And Abs(wvec(i) <= eps)) If (Not testFlag) Then GoTo nextL Next i GoTo exitNout nextL: Next L Next Nout exitNout: End Sub __________________________________________________________________________________ Code 4.4: VBA code of the Markowitz( ) routine. __________________________________________________________________________________ Option Explicit Private Const nmax = 10, Ncmax = 252 Private Const eps = 1 * 10 ^ -14 _____________________________________________________________________________________________________________ Sub MVO() Dim n As Integer Dim mvec(1 To nmax) As Double Dim uvec(1 To nmax) As Double Dim vcmatrix(1 To nmax, 1 To nmax) As Double Dim mport As Double Dim riskfree As Double Dim wvec(1 To nmax) As Double Dim w0 As Double Dim i As Integer, j As Integer n = Range("K15").Value mport = Range("D18").Value riskfree = Range("D17").Value For i = 1 To n mvec(i) = Range("C5").Offset(i - 1) uvec(i) = Range("B5").Offset(i - 1) For j = 1 To n: vcmatrix(i, j) = Range("J5").Offset(j - 1, i - 1): Next j Next i Call Markowitz(n, mvec, uvec, vcmatrix, mport, riskfree, wvec, w0) For i = 1 To nmax: Range("F5").Offset(i - 1) = wvec(i): Next i Range("F15").Value = w0 End Sub __________________________________________________________________________________ Code 4.5: VBA code of the MVO( ) routine.