Chapter 3: Portfolio Returns

3.1: Constructing Portfolio Returns (Long Way)

  • The return on a portfolio of securities is equal to the weighted average of the returnsof the individual securities in the portfolio with the weight calculated as the percentage invested in that security relative to the total amount 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 period

  • The data object multi calculated earlier contains the adjusted prices of AMZN, GSPC, YHOO, and IBM

  • Since we only need the first and last observations in the object, create a new data object period.ret that contains the observation for Dec 31, 2010 and Dec 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 this 3-year period is equal to the percentage change in the adjusted closing pric over those two dates

  • Since there are only two observations in rets, use the Delt command

  • When applying the Delt command to all four securities, use the lapply command

  • The output below shows that we get a 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

  • Because the data is in a list object, convert it to a data.frame to continue the calculations

  • 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, create variables representing the dollar amount of investment in each security

  • Then, calculate the weight of each security by calculating the percentage invested in that security divided by the total amount invested

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 Returns

  • After calculating weights, now calculate returns

  • The portfolio return is the weighted average return of each security in the portfolio

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 grows, it will be harder to implement the previous equation

  • Matrix algebra is a convenient way to clculate portfolio returns when there are many securities in the portfolio

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 doing well, compare the returns of our investment to that of a benchmark

  • In this section, we will learn how to make an equal-weighted (EW) index and a value-weighted (VW) index

Step 1: Importing the Price Data

  • We will make a EW and VW portfolio consisting of AMZN, YHOO, IBM stock using returns in 2013

  • Create a common data object that contains the data necessary to construct the EW and VW portfolios

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 closing prices, we can calculate the total returns 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 a data.frame Object and Subset Data

  • Follow the same technique used in subsetting data using dates in Chapter 1 to subset port to only include data from Dec 31, 2012 to Dec 1, 2013
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

Equal-Weighted Portfolio

  • An EW index gives equal weight to both small and large firms and is sometimes used to capture the small cap stock premium

  • Indexes are rebalanced quarterly, which means that in between quarters the constituent weights are allowed to fluctuate based on their performance

Step 1: Keep Only Variables We Need to Construct EW Portfolio

  • First take from port only the variables you need, which are the returns from AMZN, YHOO, and IBM
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

  • Convert the data to gross returns by adding one to each security’s returns

  • Since gross returns are simply one plus the net return, 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

  • Subset ewport by data from Dec 31, 2012 to March 31, 2013

  • Use the cumprod command to calculate the cumulative gross returns for each security during the quarter

  • Use the variable num.sec instead of the number 3 because in the program it is easier to identify a variable instead of a number

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

  • Steps for the second quarter are pretty similar to that of the first quarter calculation
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: Calcuate EW Portfolio Values for 3Q 2013

  • The technique for constructing the third quarter 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

  • Do the same above for quarter 4
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 Portfoliio Values into One Data Object

  • Now we can combine the four quarterly EW portfolio values into one data object ew.portval using the rbind command.
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
  • The output here summarizes the performace of an EW portfolio in which money is invested at the closing prices on Dec 31, 2012 and was held through the end of Dec 31, 2013