Chapter 3

This chapter discusses the returns of a basket of securities or portfolio returns. A portfolio’s return is simply the weighted-average return of the securities in the portfolio with the weights given by the amount of money you invest in each security. We demonstrate how this calculation is performed using two approaches: the long way in which all steps are laid out and the use of matrix algebra, which we will later use when performing mean-variance optimization across multiple securities. We then show how to construct benchmark portfolio returns, which are returns of a hypothetical portfolio that we can use to compare the performance of our portfolio. Two common approaches in benchmark portfolio construction is the use of an equalweighted portfolio and a value-weighted portfolio with quarterly rebalancing.

3.1: Constructing Portfolio Logs (the long way)

In prior sections we discussed how to calculate returns of individual securities. Most investors likely have more than one security in their portfolio. In those cases, we may be interested in knowing the portfolio return. It turns out that the return on a portfolio of securities is equal to the weighted-average of the returns of the individual securities in the portfolio with the weight calculated as the percentage invested in that security relative to the total amount invested in the portfolio

step 1: Find First and Last Adjusted Closing Price for Each Security Over the Investment Price

The data object multi calculated earlier contains the adjusted prices of AMZN, GSPC, YHOO, and IBM. Since we only need the first and last observation in the data object, we can create a new data object period.ret that contains the observation for December 31, 2010 and December 31, 2013.

period.ret<-multi[c(1,nrow(multi)),]
period.ret
##            AMZN.Adjusted GSPC.Adjusted YHOO.Adjusted IBM.Adjusted
## 2010-12-31        180.00       1257.64         16.63     125.8031
## 2013-12-31        398.79       1848.36         40.44     169.4835

step 2: Calculate Returns for Each Security over the investment period

The total return over the 3-year period December 31, 2010 to December 31, 2013 is equal to the percentage change in the adjusted closing price over those two dates. Earlier we used the Delt command to calculate the percentage change between consecutive observations in a time series. Since we only have two observations in rets (although they are temporally 3 years apart), we can use the Delt command. To apply the Delt command to all four securities, we can use the lapply command. The lapply command applies a function to each of the variables in the data object. In this case, we are applying Delt to each variable. The output below shows that we get the net total return for each security in a list object.

rets<-lapply(period.ret,Delt)
rets
## $AMZN.Adjusted
##            Delt.1.arithmetic
## 2010-12-31                NA
## 2013-12-31            1.2155
## 
## $GSPC.Adjusted
##            Delt.1.arithmetic
## 2010-12-31                NA
## 2013-12-31         0.4697051
## 
## $YHOO.Adjusted
##            Delt.1.arithmetic
## 2010-12-31                NA
## 2013-12-31           1.43175
## 
## $IBM.Adjusted
##            Delt.1.arithmetic
## 2010-12-31                NA
## 2013-12-31         0.3472126

step 3: Convert to a data.frame and cleanup data

Since the returns data is in a list object, we have to convert it to a data.frame to continue with our calculations. We convert rets into a data frame using the data.frame command.

rets<-data.frame(rets)
rets
##            Delt.1.arithmetic Delt.1.arithmetic.1 Delt.1.arithmetic.2
## 2010-12-31                NA                  NA                  NA
## 2013-12-31            1.2155           0.4697051             1.43175
##            Delt.1.arithmetic.3
## 2010-12-31                  NA
## 2013-12-31           0.3472126
rets<-rets[2,]*100
names(rets)<-paste(c("AMZN","GSPC","YHOO","IBM"))
rets
##              AMZN     GSPC    YHOO      IBM
## 2013-12-31 121.55 46.97051 143.175 34.72126

step 4: calculate weight of each security in the portfolio

To calculate the weights, we create variables representing the dollar amount of investment in each security. We then calculate the weight of each security by calculating the percentage invested in that security divided by the total amount invested, which in this case is equal to $100,000. As we can see, AMZN has a 50% weight, GSPC has a 10% weight, YHOO has a 30% weight, and IBM has a 10% weight.

i.AMZN<-50000
i.GSPC<-10000
i.YHOO<-30000
i.IBM<-10000
w.AMZN<-i.AMZN/(i.AMZN+i.GSPC+i.YHOO+i.IBM)
w.AMZN
## [1] 0.5
w.GSPC<-i.GSPC/(i.AMZN+i.GSPC+i.YHOO+i.IBM)
w.GSPC
## [1] 0.1
w.YHOO<-i.YHOO/(i.AMZN+i.GSPC+i.YHOO+i.IBM)
w.YHOO
## [1] 0.3
w.IBM<-i.IBM/(i.AMZN+i.GSPC+i.YHOO+i.IBM)
w.IBM
## [1] 0.1

step 5: calculate portfolio return

After calculating the weights, we can now calculate the returns. The portfolio return is the weighted average return of each security in the portfolio. As the output shows, the portfolio return over the period is 112%.

port.ret.4asset<-w.AMZN*rets$AMZN+w.GSPC*rets$GSPC+
  w.YHOO*rets$YHOO+w.IBM*rets$IBM
port.ret.4asset
## [1] 111.8967

3.2: constructing portfolio returns (matrix algebra)

As the number of securities in our portfolio grows, it will be too cumbersome to implement Eq. (3.2). A convenient way to calculate portfolio returns when there are many securities in the portfolio is to use matrix algebra. To implement this, we have to calculate two vectors, where a vector can be thought of as a series of numbers organized as either a row or a column. The first is a vector of weights, which in this case is 50 % for AMZN, 10% for GSPC, 30% for YHOO, and 10% for IBM. We create this using the c( … ) operator and we convert this to a matrix with one row using the matrix command with the second argument equal to one (i.e., a row vector).

wgt<-c(0.5,0.1,0.3,0.1)
mat.wgt<-matrix(wgt,1)
mat.wgt
##      [,1] [,2] [,3] [,4]
## [1,]  0.5  0.1  0.3  0.1
ret<-c(rets$AMZN,rets$GSPC,rets$YHOO,rets$IBM)
mat.ret<-matrix(ret,4)
mat.ret
##           [,1]
## [1,] 121.55001
## [2,]  46.97051
## [3,] 143.17499
## [4,]  34.72126
port.ret<-mat.wgt %*% mat.ret
port.ret
##          [,1]
## [1,] 111.8967

3.3: constructing benchmark portfolio returns

To determine whether our investment is performing well, we compare the returns of our investment to that of a benchmark. Typically, some index of comparable securities are used as the benchmark. Some benchmarks are readily-available (e.g., S&P 500 Index for large capitalization stocks). Alternatively, benchmarks can be constructed. In this section, we demonstrate how to construct an equal-weighted (EW) index and value-weighted (VW) index. We first setup the data we need to construct the indexes.

step 1: importing the price data

In this section, we will construct a hypothetical EW and VW portfolio consisting of AMZ, YHOO, and IBM stock using returns in 2013. We now create a common data object that contains the data necessary to construct the EW and VW portfolios. Since we have called in the original Yahoo Finance data for all three securities earlier, we only need to make sure that the data is still in the R workspace or memory.

data.AMZN[c(1:3,nrow(data.AMZN)),]
##            AMZN.Open AMZN.High AMZN.Low AMZN.Close AMZN.Volume
## 2010-12-31    181.96    182.30   179.51     180.00     3451900
## 2011-01-03    181.37    186.00   181.21     184.22     5331400
## 2011-01-04    186.15    187.70   183.78     185.01     5031800
## 2013-12-31    394.58    398.83   393.80     398.79     1996500
##            AMZN.Adjusted
## 2010-12-31        180.00
## 2011-01-03        184.22
## 2011-01-04        185.01
## 2013-12-31        398.79
data.YHOO[c(1:3,nrow(data.YHOO)),]
##            YHOO.Open YHOO.High YHOO.Low YHOO.Close YHOO.Volume
## 2010-12-31     16.74     16.76    16.47      16.63     7754500
## 2011-01-03     16.81     16.94    16.67      16.75    17684000
## 2011-01-04     16.71     16.83    16.57      16.59    11092800
## 2013-12-31     40.17     40.50    40.00      40.44     8291400
##            YHOO.Adjusted
## 2010-12-31         16.63
## 2011-01-03         16.75
## 2011-01-04         16.59
## 2013-12-31         40.44
data.IBM[c(1:3,nrow(data.IBM)),]
##            IBM.Open IBM.High IBM.Low IBM.Close IBM.Volume IBM.Adjusted
## 2010-12-31   146.73   147.07  145.96    146.76    2969800     125.8031
## 2011-01-03   147.21   148.20  147.14    147.48    4603800     126.4203
## 2011-01-04   147.56   148.22  146.64    147.64    5060100     126.5574
## 2013-12-31   186.49   187.79  186.30    187.57    3619700     169.4835

step 2: create object with only the relevant data

we then combine the adjusted and closing prices of the three securities

port<-data.AMZN[,c(4,6)]
port<-merge(port,data.YHOO[,c(4,6)])
port<-merge(port,data.IBM[,c(4,6)])
port[c(1:3,nrow(port)),]
##            AMZN.Close AMZN.Adjusted YHOO.Close YHOO.Adjusted IBM.Close
## 2010-12-31     180.00        180.00      16.63         16.63    146.76
## 2011-01-03     184.22        184.22      16.75         16.75    147.48
## 2011-01-04     185.01        185.01      16.59         16.59    147.64
## 2013-12-31     398.79        398.79      40.44         40.44    187.57
##            IBM.Adjusted
## 2010-12-31     125.8031
## 2011-01-03     126.4203
## 2011-01-04     126.5574
## 2013-12-31     169.4835

step 3: calculate returns of each security

using the adjusted close prices, we calculate the total return of AMZN, YHOO, and IBM

port$AMZN.ret<-Delt(port$AMZN.Adjusted)
port$YHOO.ret<-Delt(port$YHOO.Adjusted)
port$IBM.ret<-Delt(port$IBM.Adjusted)
port[c(1:3,nrow(port)),]
##            AMZN.Close AMZN.Adjusted YHOO.Close YHOO.Adjusted IBM.Close
## 2010-12-31     180.00        180.00      16.63         16.63    146.76
## 2011-01-03     184.22        184.22      16.75         16.75    147.48
## 2011-01-04     185.01        185.01      16.59         16.59    147.64
## 2013-12-31     398.79        398.79      40.44         40.44    187.57
##            IBM.Adjusted    AMZN.ret     YHOO.ret     IBM.ret
## 2010-12-31     125.8031          NA           NA          NA
## 2011-01-03     126.4203 0.023444450  0.007215935 0.004905977
## 2011-01-04     126.5574 0.004288318 -0.009552239 0.001084913
## 2013-12-31     169.4835 0.013778412  0.005970099 0.006222858

step 4: convert to data.frame object and subset data

we follow the same technique we discussed in subsetting data using in chap. 1 to subset port to only include data from december 31, 2012 to december 31, 2013. we leave the december 31, 2010 data in because, looking ahead, we need that observation as a placeholder for later calculations.

port<-cbind(data.frame(index(port)),
            data.frame(port))
names(port)[1]<-paste("date")
port[c(1:3,nrow(port)),]
##                  date AMZN.Close AMZN.Adjusted YHOO.Close YHOO.Adjusted
## 2010-12-31 2010-12-31     180.00        180.00      16.63         16.63
## 2011-01-03 2011-01-03     184.22        184.22      16.75         16.75
## 2011-01-04 2011-01-04     185.01        185.01      16.59         16.59
## 2013-12-31 2013-12-31     398.79        398.79      40.44         40.44
##            IBM.Close IBM.Adjusted    AMZN.ret     YHOO.ret     IBM.ret
## 2010-12-31    146.76     125.8031          NA           NA          NA
## 2011-01-03    147.48     126.4203 0.023444450  0.007215935 0.004905977
## 2011-01-04    147.64     126.5574 0.004288318 -0.009552239 0.001084913
## 2013-12-31    187.57     169.4835 0.013778412  0.005970099 0.006222858
port<-subset(port,
             port$date>="2012-12-31"&
               port$date<="2013-12-31")
port[c(1:3,nrow(port)),]
##                  date AMZN.Close AMZN.Adjusted YHOO.Close YHOO.Adjusted
## 2012-12-31 2012-12-31     250.87        250.87      19.90         19.90
## 2013-01-02 2013-01-02     257.31        257.31      20.08         20.08
## 2013-01-03 2013-01-03     258.48        258.48      19.78         19.78
## 2013-12-31 2013-12-31     398.79        398.79      40.44         40.44
##            IBM.Close IBM.Adjusted    AMZN.ret     YHOO.ret      IBM.ret
## 2012-12-31    191.55     169.7850 0.023207448  0.020512821  0.009060744
## 2013-01-02    196.35     174.0396 0.025670679  0.009045226  0.025058746
## 2013-01-03    195.27     173.0823 0.004547095 -0.014940189 -0.005500391
## 2013-12-31    187.57     169.4835 0.013778412  0.005970099  0.006222858

3.3.1: equal-weighted portfolio

An equal-weighted (EW) index gives equal weight to small firms and large firms. As such, an EW index is sometimes considered as an approach to capture the small capitalization stock premium (i.e., the belief that small capitalization stocks yield higher returns over large capitalization stocks).1 An example of EW indexes is the S&P500EqualWeightIndex,whichStandard&Poor’screatedinresponsetoneeds of the market for an “official” EW index version of the S&P 500 Index, and those provided by MSCI for developed markets, emerging markets, and all countries.2 These indexes are rebalanced quarterly, which means that in between quarters the constituent weights are allowed to fluctuate based on their performance. We follow this quarterly rebalancing approach.

step 1: keep only variables we need to construct EW portfolio

we first take from port only the variables that we need, which are the returns of AMZN, YHOO, and IBM. To make calling in the variables easier, we also rename the return variables to only be the tickers. in addition, we renumber the index to denote the observation number.

ewport<-port[c(1,8:10)]
ewport[c(1:3,nrow(ewport)),]
##                  date    AMZN.ret     YHOO.ret      IBM.ret
## 2012-12-31 2012-12-31 0.023207448  0.020512821  0.009060744
## 2013-01-02 2013-01-02 0.025670679  0.009045226  0.025058746
## 2013-01-03 2013-01-03 0.004547095 -0.014940189 -0.005500391
## 2013-12-31 2013-12-31 0.013778412  0.005970099  0.006222858
names(ewport)<-paste(c("date","AMZN","YHOO","IBM"))
rownames(ewport)<-seq(1:nrow(ewport))
ewport[c(1:3,nrow(ewport)),]
##           date        AMZN         YHOO          IBM
## 1   2012-12-31 0.023207448  0.020512821  0.009060744
## 2   2013-01-02 0.025670679  0.009045226  0.025058746
## 3   2013-01-03 0.004547095 -0.014940189 -0.005500391
## 253 2013-12-31 0.013778412  0.005970099  0.006222858

step 2: converting net returns to gross returns

we then convert the data to gross returns, by adding one to each security’s returns. note that to reduce the number of varialbes we use, we are overwriting the net return series. we need to be careful when overwriting a series so as not to lose any information. since gross returns are simply one plus the net return, we can glean from the gross return series what we would need from the net return series.

ewport$AMZN<-1+ewport$AMZN
ewport$YHOO<-1+ewport$YHOO
ewport$IBM<-1+ewport$IBM
ewport[c(1:3,nrow(ewport)),]
##           date     AMZN      YHOO       IBM
## 1   2012-12-31 1.023207 1.0205128 1.0090607
## 2   2013-01-02 1.025671 1.0090452 1.0250587
## 3   2013-01-03 1.004547 0.9850598 0.9944996
## 253 2013-12-31 1.013778 1.0059701 1.0062229

step 3: calculate EW portfolio values for 1Q 2013

Now, we shall start with the EW portfolio values in the first quarter of 2013. As such, we subset ewport by data from December 31, 2012 to March 31, 2013. The reason why we would want to include December 31, 2012 is because, when we want to determine how much we made based on the returns in 2013, we are implicitly making the assumption that the ivnestment was made at the closing price on the last trading day of 2012

ew.q1<-subset(ewport,
              ewport$date>=as.Date("2012-12-31")&
                ewport$date<=as.Date("2013-03-31"))
ew.q1[c(1:3,nrow(ew.q1)),]
##          date     AMZN      YHOO       IBM
## 1  2012-12-31 1.023207 1.0205128 1.0090607
## 2  2013-01-02 1.025671 1.0090452 1.0250587
## 3  2013-01-03 1.004547 0.9850598 0.9944996
## 61 2013-03-28 1.004485 0.9974566 1.0114278
ew.q1[1,2:4]<-1
ew.q1$AMZN<-cumprod(ew.q1$AMZN)
ew.q1$YHOO<-cumprod(ew.q1$YHOO)
ew.q1$IBM<-cumprod(ew.q1$IBM)
ew.q1[c(1:3,nrow(ew.q1)),]
##          date     AMZN      YHOO      IBM
## 1  2012-12-31 1.000000 1.0000000 1.000000
## 2  2013-01-02 1.025671 1.0090452 1.025059
## 3  2013-01-03 1.030335 0.9939699 1.019421
## 61 2013-03-28 1.062263 1.1824121 1.118235
num.sec<-3
ew.q1$AMZN.idx<-(1/num.sec)*ew.q1$AMZN
ew.q1$YHOO.idx<-(1/num.sec)*ew.q1$YHOO
ew.q1$IBM.idx<-(1/num.sec)*ew.q1$IBM
ew.q1[c(1:3,nrow(ew.q1)),]
##          date     AMZN      YHOO      IBM  AMZN.idx  YHOO.idx   IBM.idx
## 1  2012-12-31 1.000000 1.0000000 1.000000 0.3333333 0.3333333 0.3333333
## 2  2013-01-02 1.025671 1.0090452 1.025059 0.3418902 0.3363484 0.3416862
## 3  2013-01-03 1.030335 0.9939699 1.019421 0.3434448 0.3313233 0.3398068
## 61 2013-03-28 1.062263 1.1824121 1.118235 0.3540878 0.3941374 0.3727449
q1.val<-data.frame(rowSums(ew.q1[,5:7]))
q1.val[c(1:3,nrow(q1.val)),]
## [1] 1.000000 1.019925 1.014575 1.120970
names(q1.val)<-paste("port.val")
q1.val$date<-ew.q1$date
q1.val[c(1:3,nrow(q1.val)),]
##    port.val       date
## 1  1.000000 2012-12-31
## 2  1.019925 2013-01-02
## 3  1.014575 2013-01-03
## 61 1.120970 2013-03-28
q2.inv<-q1.val[nrow(q1.val),1]
q2.inv
## [1] 1.12097

step 4: calculate EW portfolio values for 2Q 2013

the steps for the second quarter are pretty similar to that of the first quarter calculation except for this one change (and changing references from the first quarter to the second quarter).

ew.q2<-subset(ewport,
              ewport$date>=as.Date("2013-04-01")&
                ewport$date<=as.Date("2013-06-30"))
ew.q2[c(1:3,nrow(ew.q2)),]
##           date      AMZN      YHOO       IBM
## 62  2013-04-01 0.9816878 0.9987250 0.9956868
## 63  2013-04-02 1.0065365 1.0119149 1.0093229
## 64  2013-04-03 0.9837080 0.9831791 0.9920694
## 125 2013-06-28 1.0005045 0.9866510 0.9767953
ew.q2$AMZN<-cumprod(ew.q2$AMZN)
ew.q2$YHOO<-cumprod(ew.q2$YHOO)
ew.q2$IBM<-cumprod(ew.q2$IBM)
ew.q2[c(1:3,nrow(ew.q2)),]
##           date      AMZN      YHOO       IBM
## 62  2013-04-01 0.9816878 0.9987250 0.9956868
## 63  2013-04-02 0.9881047 1.0106247 1.0049695
## 64  2013-04-03 0.9720065 0.9936251 0.9969995
## 125 2013-06-28 1.0420279 1.0679982 0.9001677
ew.q2$AMZN.idx<-(q2.inv/num.sec)*ew.q2$AMZN
ew.q2$YHOO.idx<-(q2.inv/num.sec)*ew.q2$YHOO
ew.q2$IBM.idx<-(q2.inv/num.sec)*ew.q2$IBM
ew.q2[c(1:3,nrow(ew.q2)),]
##           date      AMZN      YHOO       IBM  AMZN.idx  YHOO.idx   IBM.idx
## 62  2013-04-01 0.9816878 0.9987250 0.9956868 0.3668142 0.3731802 0.3720450
## 63  2013-04-02 0.9881047 1.0106247 1.0049695 0.3692119 0.3776267 0.3755136
## 64  2013-04-03 0.9720065 0.9936251 0.9969995 0.3631967 0.3712746 0.3725355
## 125 2013-06-28 1.0420279 1.0679982 0.9001677 0.3893607 0.3990646 0.3363537
q2.val<-data.frame(rowSums(ew.q2[,5:7]))
q2.val[c(1:3,nrow(q2.val)),]
## [1] 1.112039 1.122352 1.107007 1.124779
names(q2.val)<-paste("port.val")
q2.val$date<-ew.q2$date
q2.val[c(1:3,nrow(q2.val)),]
##     port.val       date
## 62  1.112039 2013-04-01
## 63  1.122352 2013-04-02
## 64  1.107007 2013-04-03
## 125 1.124779 2013-06-28
q3.inv<-q2.val[nrow(q2.val),1]
q3.inv
## [1] 1.124779

step 5: calculate EW portfolio values for 3Q 2013

again, the technique for constructing the third quarter EW portfolio values is similar to the code for the first and second quarters.

ew.q3<-subset(ewport,
              ewport$date >= as.Date("2013-07-01") &
                ewport$date <= as.Date("2013-09-30"))
ew.q3[c(1:3,nrow(ew.q3)),]
##           date      AMZN      YHOO       IBM
## 126 2013-07-01 1.0158810 1.0043773 1.0008895
## 127 2013-07-02 1.0057781 0.9900951 1.0011502
## 128 2013-07-03 1.0010573 1.0240096 1.0091384
## 189 2013-09-30 0.9893358 0.9886736 0.9906912
ew.q3$AMZN<-cumprod(ew.q3$AMZN)
ew.q3$YHOO<-cumprod(ew.q3$YHOO)
ew.q3$IBM<-cumprod(ew.q3$IBM)
ew.q3[c(1:3,nrow(ew.q3)),]
##           date     AMZN     YHOO       IBM
## 126 2013-07-01 1.015881 1.004377 1.0008895
## 127 2013-07-02 1.021751 0.994429 1.0020407
## 128 2013-07-03 1.022831 1.018305 1.0111977
## 189 2013-09-30 1.125860 1.319936 0.9738145
ew.q3$AMZN.idx<-(q3.inv/num.sec)*ew.q3$AMZN
ew.q3$YHOO.idx<-(q3.inv/num.sec)*ew.q3$YHOO
ew.q3$IBM.idx<-(q3.inv/num.sec)*ew.q3$IBM
ew.q3[c(1:3,nrow(ew.q3)),]
##           date     AMZN     YHOO       IBM  AMZN.idx  YHOO.idx   IBM.idx
## 126 2013-07-01 1.015881 1.004377 1.0008895 0.3808805 0.3765675 0.3752598
## 127 2013-07-02 1.021751 0.994429 1.0020407 0.3830813 0.3728376 0.3756914
## 128 2013-07-03 1.022831 1.018305 1.0111977 0.3834863 0.3817893 0.3791246
## 189 2013-09-30 1.125860 1.319936 0.9738145 0.4221145 0.4948789 0.3651087
q3.val<-data.frame(rowSums(ew.q3[,5:7]))
q3.val[c(1:3,nrow(q3.val)),]
## [1] 1.132708 1.131610 1.144400 1.282102
names(q3.val)<-paste("port.val")
q3.val$date<-ew.q3$date
q3.val[c(1:3,nrow(q3.val)),]
##     port.val       date
## 126 1.132708 2013-07-01
## 127 1.131610 2013-07-02
## 128 1.144400 2013-07-03
## 189 1.282102 2013-09-30
q4.inv<-q3.val[nrow(q3.val),1]
q4.inv
## [1] 1.282102

step 6: calculate EW portfolio values for 4Q 2013

The technique to construct the fourth quarter EW portfolio values is similar to the prior quarters

ew.q4<-subset(ewport,
              ewport$date >= as.Date("2013-10-01") &
                ewport$date <= as.Date("2013-12-31"))
ew.q4[c(1:3,nrow(ew.q4)),]
##           date      AMZN      YHOO       IBM
## 190 2013-10-01 1.0265801 1.0343685 1.0064803
## 191 2013-10-02 0.9986291 0.9950451 0.9923812
## 192 2013-10-03 0.9820598 0.9923844 0.9940527
## 253 2013-12-31 1.0137784 1.0059701 1.0062229
ew.q4$AMZN<-cumprod(ew.q4$AMZN)
ew.q4$YHOO<-cumprod(ew.q4$YHOO)
ew.q4$IBM<-cumprod(ew.q4$IBM)
ew.q4[c(1:3,nrow(ew.q4)),]
##           date     AMZN     YHOO       IBM
## 190 2013-10-01 1.026580 1.034368 1.0064803
## 191 2013-10-02 1.025173 1.029243 0.9988120
## 192 2013-10-03 1.006781 1.021405 0.9928718
## 253 2013-12-31 1.275557 1.219174 1.0183461
ew.q4$AMZN.idx<-(q4.inv/num.sec)*ew.q4$AMZN
ew.q4$YHOO.idx<-(q4.inv/num.sec)*ew.q4$YHOO
ew.q4$IBM.idx<-(q4.inv/num.sec)*ew.q4$IBM
ew.q4[c(1:3,nrow(ew.q4)),]
##           date     AMZN     YHOO       IBM  AMZN.idx  YHOO.idx   IBM.idx
## 190 2013-10-01 1.026580 1.034368 1.0064803 0.4387268 0.4420553 0.4301368
## 191 2013-10-02 1.025173 1.029243 0.9988120 0.4381253 0.4398650 0.4268597
## 192 2013-10-03 1.006781 1.021405 0.9928718 0.4302653 0.4365151 0.4243210
## 253 2013-12-31 1.275557 1.219174 1.0183461 0.5451312 0.5210352 0.4352078
q4.val<-data.frame(rowSums(ew.q4[5:7]))
q4.val[c(1:3,nrow(q4.val)),]
## [1] 1.310919 1.304850 1.291101 1.501374
names(q4.val)<-paste("port.val")
q4.val$date<-ew.q4$date
q4.val[c(1:3,nrow(q4.val)),]
##     port.val       date
## 190 1.310919 2013-10-01
## 191 1.304850 2013-10-02
## 192 1.291101 2013-10-03
## 253 1.501374 2013-12-31

step 7: combine quarterly EW portfolio values itno one data object

now, we can combine the four quarterly EW portfolio values into one data object ew.port val using the rbind command. the rbind command allows us to stack the four data objects one on top of the other

ew.portval<-rbind(q1.val,q2.val,q3.val,q4.val)
ew.portval[c(1:3,nrow(ew.portval)),]
##     port.val       date
## 1   1.000000 2012-12-31
## 2   1.019925 2013-01-02
## 3   1.014575 2013-01-03
## 253 1.501374 2013-12-31

3.3.2: Value-Weighted Portfolio

An alternative way to construct a portfolio of securities is to use value-weighted returns or capitalization-weighted returns. Some of the major indexes use some form of value-weighting, such as the S&P 500 Index. in a VW portfolio, the returns of larger firms are given more weight. In the context of say a VW sector index, one can think of capitalization-weighting as an approach to tracking the changes in the size of that sector

step 1: Keep only variables we need to construct VW portfolio

To start constructing a VW portfolio, we first extract from port the close and adjusted closing price variables.

vwport<-port[,c(1,2,4,6,8:10)]
vwport[c(1:3,nrow(vwport)),]
##                  date AMZN.Close YHOO.Close IBM.Close    AMZN.ret
## 2012-12-31 2012-12-31     250.87      19.90    191.55 0.023207448
## 2013-01-02 2013-01-02     257.31      20.08    196.35 0.025670679
## 2013-01-03 2013-01-03     258.48      19.78    195.27 0.004547095
## 2013-12-31 2013-12-31     398.79      40.44    187.57 0.013778412
##                YHOO.ret      IBM.ret
## 2012-12-31  0.020512821  0.009060744
## 2013-01-02  0.009045226  0.025058746
## 2013-01-03 -0.014940189 -0.005500391
## 2013-12-31  0.005970099  0.006222858
rownames(vwport)<-seq(1:nrow(vwport))
vwport[c(1:3,nrow(vwport)),]
##           date AMZN.Close YHOO.Close IBM.Close    AMZN.ret     YHOO.ret
## 1   2012-12-31     250.87      19.90    191.55 0.023207448  0.020512821
## 2   2013-01-02     257.31      20.08    196.35 0.025670679  0.009045226
## 3   2013-01-03     258.48      19.78    195.27 0.004547095 -0.014940189
## 253 2013-12-31     398.79      40.44    187.57 0.013778412  0.005970099
##          IBM.ret
## 1    0.009060744
## 2    0.025058746
## 3   -0.005500391
## 253  0.006222858

step 2: converting net returns to gross returns

similar to what we did when we constructed the EW portfolio returns, we overwrite the net returns with gross returns

vwport$AMZN.ret<-1+vwport$AMZN.ret
vwport$YHOO.ret<-1+vwport$YHOO.ret
vwport$IBM.ret<-1+vwport$IBM.ret
vwport[c(1:3,nrow(vwport)),]
##           date AMZN.Close YHOO.Close IBM.Close AMZN.ret  YHOO.ret
## 1   2012-12-31     250.87      19.90    191.55 1.023207 1.0205128
## 2   2013-01-02     257.31      20.08    196.35 1.025671 1.0090452
## 3   2013-01-03     258.48      19.78    195.27 1.004547 0.9850598
## 253 2013-12-31     398.79      40.44    187.57 1.013778 1.0059701
##       IBM.ret
## 1   1.0090607
## 2   1.0250587
## 3   0.9944996
## 253 1.0062229

step 3: calculate the market capitalization of each security in the portfolio

Now, we have to construct the market capitalization weights for each security at the end of each quarter. A security’s market cap is equal to its price multiplied by its shares outstanding. As such, we need to get the data for those two components. Let us first discuss how to find the price that is applicable at the end of each quarter. Construct series of calendar days since the end of the quarter may not be a trading day, we should create a date series that contains all calendar days between December 31, 2012 to December 31, 2013. Note that the output shows we have dates that include non-trading days such as January 1, 2013, which is New Year’s Day and is a stock market trading holiday

date<-seq(as.Date("2012-12-31"),as.Date("2013-12-31"),by=1)
date<-data.frame(date)
date[c(1:3,nrow(date)),]
## [1] "2012-12-31" "2013-01-01" "2013-01-02" "2013-12-31"
PRICE.qtr<-vwport[,c(1,2,3,4)]
PRICE.qtr[c(1:3,nrow(PRICE.qtr)),]
##           date AMZN.Close YHOO.Close IBM.Close
## 1   2012-12-31     250.87      19.90    191.55
## 2   2013-01-02     257.31      20.08    196.35
## 3   2013-01-03     258.48      19.78    195.27
## 253 2013-12-31     398.79      40.44    187.57
PRICE.qtr<-na.locf(merge(x=date,y=PRICE.qtr,by="date",all.x=TRUE))
PRICE.qtr[c(1:3,nrow(PRICE.qtr)),]
##           date AMZN.Close YHOO.Close IBM.Close
## 1   2012-12-31     250.87      19.90    191.55
## 2   2013-01-01     250.87      19.90    191.55
## 3   2013-01-02     257.31      20.08    196.35
## 366 2013-12-31     398.79      40.44    187.57
PRICE.qtr<-subset(PRICE.qtr,
                  PRICE.qtr$date==as.Date("2012-12-31") |
                    PRICE.qtr$date==as.Date("2013-03-31") |
                    PRICE.qtr$date==as.Date("2013-06-30") |
                    PRICE.qtr$date==as.Date("2013-09-30"))
PRICE.qtr
##           date AMZN.Close YHOO.Close IBM.Close
## 1   2012-12-31     250.87      19.90    191.55
## 91  2013-03-31     266.49      23.53    213.30
## 182 2013-06-30     277.69      25.13    191.11
## 274 2013-09-30     312.64      33.17    185.18
PRICE.qtr$AMZN.shout<-c(454000000,455000000,457000000,458000000)
PRICE.qtr$YHOO.shout<-c(1115233000,1084766000,1065046000,1013059000)
PRICE.qtr$IBM.shout<-c(111737676,1108794396,1095425823,1085854383)
PRICE.qtr
##           date AMZN.Close YHOO.Close IBM.Close AMZN.shout YHOO.shout
## 1   2012-12-31     250.87      19.90    191.55   4.54e+08 1115233000
## 91  2013-03-31     266.49      23.53    213.30   4.55e+08 1084766000
## 182 2013-06-30     277.69      25.13    191.11   4.57e+08 1065046000
## 274 2013-09-30     312.64      33.17    185.18   4.58e+08 1013059000
##      IBM.shout
## 1    111737676
## 91  1108794396
## 182 1095425823
## 274 1085854383
str(PRICE.qtr)
## 'data.frame':    4 obs. of  7 variables:
##  $ date      : chr  "2012-12-31" "2013-03-31" "2013-06-30" "2013-09-30"
##  $ AMZN.Close: chr  "250.87" "266.49" "277.69" "312.64"
##  $ YHOO.Close: chr  "19.90" "23.53" "25.13" "33.17"
##  $ IBM.Close : chr  "191.55" "213.30" "191.11" "185.18"
##  $ AMZN.shout: num  4.54e+08 4.55e+08 4.57e+08 4.58e+08
##  $ YHOO.shout: num  1.12e+09 1.08e+09 1.07e+09 1.01e+09
##  $ IBM.shout : num  1.12e+08 1.11e+09 1.10e+09 1.09e+09
PRICE.qtr$date<-as.Date(PRICE.qtr$date)
PRICE.qtr$AMZN.Close<-as.numeric(PRICE.qtr$AMZN.Close)
PRICE.qtr$YHOO.Close<-as.numeric(PRICE.qtr$YHOO.Close)
PRICE.qtr$IBM.Close<-as.numeric(PRICE.qtr$IBM.Close)
str(PRICE.qtr)
## 'data.frame':    4 obs. of  7 variables:
##  $ date      : Date, format: "2012-12-31" "2013-03-31" ...
##  $ AMZN.Close: num  251 266 278 313
##  $ YHOO.Close: num  19.9 23.5 25.1 33.2
##  $ IBM.Close : num  192 213 191 185
##  $ AMZN.shout: num  4.54e+08 4.55e+08 4.57e+08 4.58e+08
##  $ YHOO.shout: num  1.12e+09 1.08e+09 1.07e+09 1.01e+09
##  $ IBM.shout : num  1.12e+08 1.11e+09 1.10e+09 1.09e+09
weights<-PRICE.qtr
weights$AMZN.mcap<-weights$AMZN.Close*weights$AMZN.shout
weights$YHOO.mcap<-weights$YHOO.Close*weights$YHOO.shout
weights$IBM.mcap<-weights$IBM.Close*weights$IBM.shout
weights
##           date AMZN.Close YHOO.Close IBM.Close AMZN.shout YHOO.shout
## 1   2012-12-31     250.87      19.90    191.55   4.54e+08 1115233000
## 91  2013-03-31     266.49      23.53    213.30   4.55e+08 1084766000
## 182 2013-06-30     277.69      25.13    191.11   4.57e+08 1065046000
## 274 2013-09-30     312.64      33.17    185.18   4.58e+08 1013059000
##      IBM.shout    AMZN.mcap   YHOO.mcap     IBM.mcap
## 1    111737676 113894980000 22193136700  21403351838
## 91  1108794396 121252950000 25524543980 236505844667
## 182 1095425823 126904330000 26764605980 209346829034
## 274 1085854383 143189120000 33603167030 201078514644
weights$tot.mcap<-rowSums(weights[8:10])
weights
##           date AMZN.Close YHOO.Close IBM.Close AMZN.shout YHOO.shout
## 1   2012-12-31     250.87      19.90    191.55   4.54e+08 1115233000
## 91  2013-03-31     266.49      23.53    213.30   4.55e+08 1084766000
## 182 2013-06-30     277.69      25.13    191.11   4.57e+08 1065046000
## 274 2013-09-30     312.64      33.17    185.18   4.58e+08 1013059000
##      IBM.shout    AMZN.mcap   YHOO.mcap     IBM.mcap     tot.mcap
## 1    111737676 113894980000 22193136700  21403351838 157491468538
## 91  1108794396 121252950000 25524543980 236505844667 383283338647
## 182 1095425823 126904330000 26764605980 209346829034 363015765014
## 274 1085854383 143189120000 33603167030 201078514644 377870801674

step 4: calculate quarter-end weights of each security in the portfolio

We can now calculate the quarter-end weights for the three securities by dividing each security’s market cap by the combined market cap of the three securities

weights$AMZN.wgt<-weights$AMZN.mcap/weights$tot.mcap
weights$YHOO.wgt<-weights$YHOO.mcap/weights$tot.mcap
weights$IBM.wgt<-weights$IBM.mcap/weights$tot.mcap
weights
##           date AMZN.Close YHOO.Close IBM.Close AMZN.shout YHOO.shout
## 1   2012-12-31     250.87      19.90    191.55   4.54e+08 1115233000
## 91  2013-03-31     266.49      23.53    213.30   4.55e+08 1084766000
## 182 2013-06-30     277.69      25.13    191.11   4.57e+08 1065046000
## 274 2013-09-30     312.64      33.17    185.18   4.58e+08 1013059000
##      IBM.shout    AMZN.mcap   YHOO.mcap     IBM.mcap     tot.mcap
## 1    111737676 113894980000 22193136700  21403351838 157491468538
## 91  1108794396 121252950000 25524543980 236505844667 383283338647
## 182 1095425823 126904330000 26764605980 209346829034 363015765014
## 274 1085854383 143189120000 33603167030 201078514644 377870801674
##      AMZN.wgt   YHOO.wgt   IBM.wgt
## 1   0.7231819 0.14091644 0.1359017
## 91  0.3163533 0.06659445 0.6170522
## 182 0.3495835 0.07372849 0.5766880
## 274 0.3789367 0.08892766 0.5321356
WEIGHT<-weights[,c(1,12:14)]
WEIGHT
##           date  AMZN.wgt   YHOO.wgt   IBM.wgt
## 1   2012-12-31 0.7231819 0.14091644 0.1359017
## 91  2013-03-31 0.3163533 0.06659445 0.6170522
## 182 2013-06-30 0.3495835 0.07372849 0.5766880
## 274 2013-09-30 0.3789367 0.08892766 0.5321356
WEIGHT$date<-WEIGHT$date+1
WEIGHT
##           date  AMZN.wgt   YHOO.wgt   IBM.wgt
## 1   2013-01-01 0.7231819 0.14091644 0.1359017
## 91  2013-04-01 0.3163533 0.06659445 0.6170522
## 182 2013-07-01 0.3495835 0.07372849 0.5766880
## 274 2013-10-01 0.3789367 0.08892766 0.5321356

step 5: calculating the quarterly VW portfolio values

This approach is similar to what we took in constructing the EW portfolio, in which we calculate the gross returns for each quarter and then apply to it the allocated value of each security based on its quarter-end weights. In the EW portfolio example, the weights were always 33 %. In the VW portfolio, as shown above, the weights used on the quarterly rebalancing dates are different. We start with creating a series of dates from December 31, 2012 to December 31, 2013 so that we can find the applicable weights at the beginning of each quarter.

date<-seq(as.Date("2012-12-31"),as.Date("2013-12-31"),by=1)
date<-data.frame(date)
date[c(1:3,nrow(date)),]
## [1] "2012-12-31" "2013-01-01" "2013-01-02" "2013-12-31"
vwret<-na.locf(merge(date,WEIGHT,by="date",all.x=TRUE))
vwret[c(1:3,nrow(vwret)),]
##           date  AMZN.wgt   YHOO.wgt   IBM.wgt
## 1   2012-12-31      <NA>       <NA>      <NA>
## 2   2013-01-01 0.7231819 0.14091644 0.1359017
## 3   2013-01-02 0.7231819 0.14091644 0.1359017
## 366 2013-12-31 0.3789367 0.08892766 0.5321356
str(vwret)
## 'data.frame':    366 obs. of  4 variables:
##  $ date    : chr  "2012-12-31" "2013-01-01" "2013-01-02" "2013-01-03" ...
##  $ AMZN.wgt: chr  NA "0.7231819" "0.7231819" "0.7231819" ...
##  $ YHOO.wgt: chr  NA "0.14091644" "0.14091644" "0.14091644" ...
##  $ IBM.wgt : chr  NA "0.1359017" "0.1359017" "0.1359017" ...
vwret$date<-as.Date(vwret$date)
vwret$AMZN.wgt<-as.numeric(vwret$AMZN.wgt)
vwret$YHOO.wgt<-as.numeric(vwret$YHOO.wgt)
vwret$IBM.wgt<-as.numeric(vwret$IBM.wgt)
vwret[c(1:3,nrow(vwret)),]
##           date  AMZN.wgt   YHOO.wgt   IBM.wgt
## 1   2012-12-31        NA         NA        NA
## 2   2013-01-01 0.7231819 0.14091644 0.1359017
## 3   2013-01-02 0.7231819 0.14091644 0.1359017
## 366 2013-12-31 0.3789367 0.08892766 0.5321356
str(vwret)
## 'data.frame':    366 obs. of  4 variables:
##  $ date    : Date, format: "2012-12-31" "2013-01-01" ...
##  $ AMZN.wgt: num  NA 0.723 0.723 0.723 0.723 ...
##  $ YHOO.wgt: num  NA 0.141 0.141 0.141 0.141 ...
##  $ IBM.wgt : num  NA 0.136 0.136 0.136 0.136 ...
q1.vw.wgt<-subset(vwret,vwret$date==as.Date("2013-01-01"))
q1.vw.wgt
##         date  AMZN.wgt  YHOO.wgt   IBM.wgt
## 2 2013-01-01 0.7231819 0.1409164 0.1359017
q2.vw.wgt<-subset(vwret,vwret$date==as.Date("2013-04-01"))
q2.vw.wgt
##          date  AMZN.wgt   YHOO.wgt   IBM.wgt
## 92 2013-04-01 0.3163533 0.06659445 0.6170522
q3.vw.wgt<-subset(vwret,vwret$date==as.Date("2013-07-01"))
q3.vw.wgt
##           date  AMZN.wgt   YHOO.wgt  IBM.wgt
## 183 2013-07-01 0.3495835 0.07372849 0.576688
q4.vw.wgt<-subset(vwret,vwret$date==as.Date("2013-10-01"))
q4.vw.wgt
##           date  AMZN.wgt   YHOO.wgt   IBM.wgt
## 275 2013-10-01 0.3789367 0.08892766 0.5321356

step 6: create pie charts of the weights

this step is not necessary, but we can visually show the different weights for each of the four quarters in a pie chart. Note that Q1 and Q2 are use the variables names as labels, while Q3 and Q4 uses re-labeled values and adds the actual percentage weight to the label. The comments in the code, which are denoted by the pound (#) sign, show where the amount and percent sign are added.