Chapter 3: Portfolio Returns

Key Issues

portfolio returns = returns of basket of securities benchmark portfolio = hypothetical portfolio that we can compare the performance of our portf

3.1 Constructing Portfolio Returns (Long Way)

Portfolio return is the weighted average of the returns of the individual securities in the portfolio. Suppose we invested $50K in AMZN, $10 in GSPC, $30 in AABA, and $10 in IBM How much would this portfolio return b/t December 31, 2010 and December 31, 2013?

Step 0: Import Price Data

# To clean up the memory of your current R session run the following line
rm(list=ls(all=TRUE))

library(quantmod)
library(xts)

#Importing Price Data
data.AMZN <- getSymbols("AMZN", from = "2010-12-31", to = "2014-01-01", auto.assign = FALSE)
data.AABA <- getSymbols("AABA", from = "2010-12-31", to = "2014-01-01", auto.assign = FALSE)
data.IBM <- getSymbols("IBM", from = "2010-12-31", to = "2014-01-01", auto.assign = FALSE)
data.GSPC <- getSymbols("^GSPC", from = "2010-12-31", to = "2014-01-01", auto.assign = FALSE)
#to = "2013-12-31" in the book was replaced by to = "2014-01-01"
#B/c that code doesn't produce the output that includes stock price of 2013-12-31the date. 

multi <- data.AMZN[, 6] # Need to create a new data object before cbinding
multi <- cbind(multi, data.GSPC[, 6], data.AABA[, 6], data.IBM[, 6])

Step 1: Find First and Last Adjusted Closing Price for Each Security Over the Investmet Period

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

Step 2: Calculate Returns for Each Security Over the Investment Period

rets <- lapply(period.ret, Delt) # lapply returns output in a list
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
## 
## $AABA.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.3472127
#rets <- mapply(Delt, data.frame(period.ret)) #mapply does the same but returns output in DF

Step 3: Convert to a data.frame and Clean up Data

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.3472127
rets <- rets[2, ] * 100
names(rets) <- paste(c("AMZN", "GSPC", "AABA", "IBM"))
rets
##              AMZN     GSPC    AABA      IBM
## 2013-12-31 121.55 46.97051 143.175 34.72127

Step 4: Calculate Weight of Each Security in the Portfolio

i.AMZN <- 50000
i.GSPC <- 10000
i.AABA <- 30000
i.IBM <- 10000

w.AMZN <- i.AMZN / (i.AMZN + i.GSPC + i.AABA + i.IBM)
w.GSPC <- i.GSPC / (i.AMZN + i.GSPC + i.AABA + i.IBM)
w.AABA <- i.AABA / (i.AMZN + i.GSPC + i.AABA + i.IBM)
w.IBM <- i.IBM / (i.AMZN + i.GSPC + i.AABA + i.IBM)
w.AMZN
## [1] 0.5
w.GSPC
## [1] 0.1
w.AABA
## [1] 0.3
w.IBM
## [1] 0.1

Step 5: Calculate Portfolio Return

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

Interpretation

  • 112 means the portfolio return over the period is 112%.

3.2 Constructing Portfolio Returns (Matrix Algebra)

The long way described above becomes too cumbersome as the number of securities in P grows.

# Creat a matrix (1 by 4) of weights
wgt <- c(0.5, 0.1, 0.3, 0.1)
mat.wgt <- matrix(wgt, 1) #1 in the 2nd arg means # of rows

# Create a matrix of (4, by 1) of returns of individual stocks
ret <- c(rets$AMZN, rets$GSPC, rets$AABA, rets$IBM)
mat.ret <- matrix(ret, 4)
mat.ret
##           [,1]
## [1,] 121.55001
## [2,]  46.97051
## [3,] 143.17499
## [4,]  34.72127

# Calculate the portfolio return using matrix multiplication
port.ret <- mat.wgt %*% mat.ret
port.ret
##          [,1]
## [1,] 111.8967

3.3 Constructing Benchmark Portfolio Returns

Construct an equal-weighted (EW) and value-weighted (VW) portfolio, consisting of AMZN, AABA, and IBM.

In this section, prepare an object, port, which will be used later to build EW and VW portfolio.

Step 1: Importing the Price Data

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.AABA[c(1:3, nrow(data.AABA)), ]
##            AABA.Open AABA.High AABA.Low AABA.Close AABA.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
##            AABA.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  174.671  175.076 173.755    146.76    2969800     123.2834
## 2011-01-03  175.243  176.421 175.159    147.48    4603800     123.8883
## 2011-01-04  175.659  176.445 174.564    147.64    5060100     124.0227
## 2013-12-31  210.610  212.078 210.395    187.57    3619700     166.0890

Step 2: Create Object with Only the Relevant Data

port <- data.AMZN[, c(4, 6)]
port <- merge(port, data.AABA[, c(4, 6)])
port <- merge(port, data.IBM[, c(4, 6)])
#port <- cbind(port, data.AABA[, c(4, 6)], data.IBM[, c(4, 6)])
port[c(1:3, nrow(port)), ]
##            AMZN.Close AMZN.Adjusted AABA.Close AABA.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     123.2834
## 2011-01-03     123.8883
## 2011-01-04     124.0227
## 2013-12-31     166.0890

Step 3: Calculate Returns of Each Security

port$AMZN.ret <- Delt(port$AMZN.Adjusted)
port$AABA.ret <- Delt(port$AABA.Adjusted)
port$IBM.ret <- Delt(port$IBM.Adjusted)
port[c(1:3, nrow(port)), ]
##            AMZN.Close AMZN.Adjusted AABA.Close AABA.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     AABA.ret     IBM.ret
## 2010-12-31     123.2834          NA           NA          NA
## 2011-01-03     123.8883 0.023444450  0.007215935 0.004906061
## 2011-01-04     124.0227 0.004288318 -0.009552239 0.001085026
## 2013-12-31     166.0890 0.013778412  0.005970099 0.006222977

Step 4: Convert to data.frame Object and Subset Data

port <- cbind(index(port), data.frame(port))
names(port)[1] <- "date"
port[c(1:3, nrow(port)), ]
##                  date AMZN.Close AMZN.Adjusted AABA.Close AABA.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     AABA.ret     IBM.ret
## 2010-12-31    146.76     123.2834          NA           NA          NA
## 2011-01-03    147.48     123.8883 0.023444450  0.007215935 0.004906061
## 2011-01-04    147.64     124.0227 0.004288318 -0.009552239 0.001085026
## 2013-12-31    187.57     166.0890 0.013778412  0.005970099 0.006222977

port <- subset(port,
               port$date >= "2012-12-31" &
               port$date <= "2013-12-31")
port[c(1:3, nrow(port)), ]
##                  date AMZN.Close AMZN.Adjusted AABA.Close AABA.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     AABA.ret      IBM.ret
## 2012-12-31    191.55     166.3845 0.023207448  0.020512821  0.009060667
## 2013-01-02    196.35     170.5539 0.025670679  0.009045226  0.025058845
## 2013-01-03    195.27     169.6158 0.004547095 -0.014940189 -0.005500554
## 2013-12-31    187.57     166.0890 0.013778412  0.005970099  0.006222977

3.3.1 Equal-Weighted Portfolio

considerd as an approach to capture the small capitalization stock premeum (the belief that small cap stock yield higher returns over larger cap stocks) An example is the S&P 500 Equal Weight Index

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

ewport <- port[, c(1, 8:10)]
ewport[c(1:3, nrow(ewport)), ]
##                  date    AMZN.ret     AABA.ret      IBM.ret
## 2012-12-31 2012-12-31 0.023207448  0.020512821  0.009060667
## 2013-01-02 2013-01-02 0.025670679  0.009045226  0.025058845
## 2013-01-03 2013-01-03 0.004547095 -0.014940189 -0.005500554
## 2013-12-31 2013-12-31 0.013778412  0.005970099  0.006222977

names(ewport)[2:4] <- c("AMZN", "AABA", "IBM")
rownames(ewport) <- seq(1, nrow(ewport), 1)
ewport[c(1:3, nrow(ewport)), ]
##           date        AMZN         AABA          IBM
## 1   2012-12-31 0.023207448  0.020512821  0.009060667
## 2   2013-01-02 0.025670679  0.009045226  0.025058845
## 3   2013-01-03 0.004547095 -0.014940189 -0.005500554
## 253 2013-12-31 0.013778412  0.005970099  0.006222977

Step 2: Convert Net Returns to Gross Returns

ewport[2:4] <- ewport[2:4] + 1
ewport[c(1:3, nrow(ewport)), ]
##           date     AMZN      AABA       IBM
## 1   2012-12-31 1.023207 1.0205128 1.0090607
## 2   2013-01-02 1.025671 1.0090452 1.0250588
## 3   2013-01-03 1.004547 0.9850598 0.9944994
## 253 2013-12-31 1.013778 1.0059701 1.0062230

Step 3: Calculate EW Portfolio Values for 1Q 2013

# Subset ewport by data from December 31, 2012 to March 31, 2013
ewq1 <- subset(ewport,
               ewport$date >= "2012-12-31" &
               ewport$date <= "2013-03-31")
ewq1[c(1:3, nrow(ewq1)), ]
##          date     AMZN      AABA       IBM
## 1  2012-12-31 1.023207 1.0205128 1.0090607
## 2  2013-01-02 1.025671 1.0090452 1.0250588
## 3  2013-01-03 1.004547 0.9850598 0.9944994
## 61 2013-03-28 1.004485 0.9974566 1.0114278

# Calculate the cumulative gross returns fro each security for Q1
ewq1[1, 2:4] <- 1
ewq1[2:4] <- cumprod(ewq1[2:4])
ewq1[c(1:3, nrow(ewq1)), ]
##          date     AMZN      AABA      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.019420
## 61 2013-03-28 1.062263 1.1824121 1.118235

# Calculate the index value for each security for Q1
num.sec <- 3
ewq1$AMZN.ind <- ewq1$AMZN / num.sec
ewq1$AABA.ind <- ewq1$AABA / num.sec
ewq1$IBM.ind <- ewq1$IBM / num.sec
ewq1[c(1:3, nrow(ewq1)), ]
##          date     AMZN      AABA      IBM  AMZN.ind  AABA.ind   IBM.ind
## 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.3416863
## 3  2013-01-03 1.030335 0.9939699 1.019420 0.3434448 0.3313233 0.3398068
## 61 2013-03-28 1.062263 1.1824121 1.118235 0.3540878 0.3941374 0.3727448

# Calculate the agrregate portfolio value on each day
q1.val <- data.frame(rowSums(ewq1[, 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 <- ewq1$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

# Pass the aggregate portfolio value at the end of Q1 to Q2
q2.inv <- q1.val[nrow(q1.val), 1]
q2.inv
## [1] 1.12097

Step 4: Calculate EW Portfolio Values for 2Q 2013

# Subset ewport by data from April 1, 2013 to June 30, 2013
ewq2 <- subset(ewport,
               ewport$date >= "2013-04-01" &
               ewport$date <= "2013-06-30")
ewq2[c(1:3, nrow(ewq2)), ]
##           date      AMZN      AABA       IBM
## 62  2013-04-01 0.9816878 0.9987250 0.9956868
## 63  2013-04-02 1.0065365 1.0119149 1.0093230
## 64  2013-04-03 0.9837080 0.9831791 0.9920694
## 125 2013-06-28 1.0005045 0.9866510 0.9767953

# Calculate the cumulative gross returns fro each security for Q2
#ewq2[1, 2:4] <- 1 This is the difference from Q1
ewq2[2:4] <- cumprod(ewq2[2:4])
ewq2[c(1:3, nrow(ewq2)), ]
##           date      AMZN      AABA       IBM
## 62  2013-04-01 0.9816878 0.9987250 0.9956868
## 63  2013-04-02 0.9881047 1.0106247 1.0049696
## 64  2013-04-03 0.9720065 0.9936251 0.9969995
## 125 2013-06-28 1.0420279 1.0679982 0.9001678

# Calculate the index value for each security for Q2
ewq2$AMZN.ind <- (q2.inv / num.sec) * ewq2$AMZN #a difference from Q1
ewq2$AABA.ind <- (q2.inv / num.sec) * ewq2$AABA 
ewq2$IBM.ind <- (q2.inv / num.sec) * ewq2$IBM 
ewq2[c(1:3, nrow(ewq2)), ]
##           date      AMZN      AABA       IBM  AMZN.ind  AABA.ind   IBM.ind
## 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.0049696 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.9001678 0.3893607 0.3990646 0.3363537

# Calculate the agrregate portfolio value on each day
q2.val <- data.frame(rowSums(ewq2[, 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 <- ewq2$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

# Pass the aggregate portfolio value at the end of Q2 to Q3
q3.inv <- q2.val[nrow(q2.val), 1]
q3.inv 
## [1] 1.124779
#$1.121 at the end of Q1 and 1.125
#Means the portfolio grown from $1.121 at the end of Q1 to $1.125 at the end of Q2
#Note that it doesn't mean that the portfolio grew 12.5% during Q2 but 12.5% during Q1-Q2
#b/c this is a cumulative measure 

Step 5: Calculate EW Portfolio Values for 3Q 2013

# Subset ewport by data from July 1, 2013 to September 30, 2013
ewq3 <- subset(ewport,
               ewport$date >= "2013-07-01" &
                 ewport$date <= "2013-09-30")
ewq3[c(1:3, nrow(ewq3)), ]
##           date      AMZN      AABA       IBM
## 126 2013-07-01 1.0158810 1.0043773 1.0008894
## 127 2013-07-02 1.0057781 0.9900951 1.0011501
## 128 2013-07-03 1.0010573 1.0240096 1.0091385
## 189 2013-09-30 0.9893358 0.9886736 0.9906917

# Calculate the cumulative gross returns fro each security for Q3
#ewq3[1, 2:4] <- 1 This is the difference from Q1
ewq3[2:4] <- cumprod(ewq3[2:4])
ewq3[c(1:3, nrow(ewq3)), ]
##           date     AMZN     AABA       IBM
## 126 2013-07-01 1.015881 1.004377 1.0008894
## 127 2013-07-02 1.021751 0.994429 1.0020405
## 128 2013-07-03 1.022831 1.018305 1.0111977
## 189 2013-09-30 1.125860 1.319936 0.9738145

# Calculate the index value for each security for Q3
ewq3$AMZN.ind <- (q3.inv / num.sec) * ewq3$AMZN #a difference from Q1
ewq3$AABA.ind <- (q3.inv / num.sec) * ewq3$AABA 
ewq3$IBM.ind <- (q3.inv / num.sec) * ewq3$IBM 
ewq3[c(1:3, nrow(ewq3)), ]
##           date     AMZN     AABA       IBM  AMZN.ind  AABA.ind   IBM.ind
## 126 2013-07-01 1.015881 1.004377 1.0008894 0.3808806 0.3765675 0.3752598
## 127 2013-07-02 1.021751 0.994429 1.0020405 0.3830813 0.3728376 0.3756914
## 128 2013-07-03 1.022831 1.018305 1.0111977 0.3834864 0.3817893 0.3791246
## 189 2013-09-30 1.125860 1.319936 0.9738145 0.4221145 0.4948789 0.3651087

# Calculate the agrregate portfolio value on each day
q3.val <- data.frame(rowSums(ewq3[, 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 <- ewq3$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

# Pass the aggregate portfolio value at the end of Q3 to Q4
q4.inv <- q3.val[nrow(q3.val), 1]
q4.inv
## [1] 1.282102

Step 6: Calculate EW Portfolio Values for 4Q 2013

# Subset ewport by data from October 1, 2013 to December 31, 2013
ewq4 <- subset(ewport,
               ewport$date >= "2013-10-01" &
                 ewport$date <= "2013-12-31")
ewq4[c(1:3, nrow(ewq4)), ]
##           date      AMZN      AABA       IBM
## 190 2013-10-01 1.0265801 1.0343685 1.0064803
## 191 2013-10-02 0.9986291 0.9950451 0.9923810
## 192 2013-10-03 0.9820598 0.9923844 0.9940527
## 253 2013-12-31 1.0137784 1.0059701 1.0062230

# Calculate the cumulative gross returns fro each security for q4
#ewq4[1, 2:4] <- 1 This is the difference from Q1
ewq4[2:4] <- cumprod(ewq4[2:4])
ewq4[c(1:3, nrow(ewq4)), ]
##           date     AMZN     AABA       IBM
## 190 2013-10-01 1.026580 1.034368 1.0064803
## 191 2013-10-02 1.025173 1.029243 0.9988119
## 192 2013-10-03 1.006781 1.021405 0.9928717
## 253 2013-12-31 1.275557 1.219174 1.0183460

# Calculate the index value for each security for q4
ewq4$AMZN.ind <- (q4.inv / num.sec) * ewq4$AMZN #a difference from Q1
ewq4$AABA.ind <- (q4.inv / num.sec) * ewq4$AABA 
ewq4$IBM.ind <- (q4.inv / num.sec) * ewq4$IBM 
ewq4[c(1:3, nrow(ewq4)), ]
##           date     AMZN     AABA       IBM  AMZN.ind  AABA.ind   IBM.ind
## 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.9988119 0.4381253 0.4398650 0.4268596
## 192 2013-10-03 1.006781 1.021405 0.9928717 0.4302653 0.4365151 0.4243210
## 253 2013-12-31 1.275557 1.219174 1.0183460 0.5451312 0.5210352 0.4352078

# Calculate the agrregate portfolio value on each day
q4.val <- data.frame(rowSums(ewq4[, 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 <- ewq4$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 into One Data Object

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

It’s considerd as an approach to track the changes in the size of the sector. Larger firms are given more weight in VW, whereas equal weights are given in EW portfolio. An example is the S&P 500 Index. It rebalances only at the beginning of each quarter.

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

vwport <- port[, c(1, 2, 4, 6, 8:10)] #port is from 3.3 Constructing Benchmark Portfolio Returns
vwport[c(1:3, nrow(vwport)), ]
##                  date AMZN.Close AABA.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
##                AABA.ret      IBM.ret
## 2012-12-31  0.020512821  0.009060667
## 2013-01-02  0.009045226  0.025058845
## 2013-01-03 -0.014940189 -0.005500554
## 2013-12-31  0.005970099  0.006222977
rownames(vwport) <- seq(1:nrow(vwport))
vwport[c(1:3, nrow(vwport)), ]
##           date AMZN.Close AABA.Close IBM.Close    AMZN.ret     AABA.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.009060667
## 2    0.025058845
## 3   -0.005500554
## 253  0.006222977

Step 2: Convert Net Returns to Gross Returns

vwport$AMZN.ret <- vwport$AMZN.ret + 1
vwport$AABA.ret <- vwport$AABA.ret + 1
vwport$IBM.ret <- vwport$IBM.ret + 1
vwport[c(1:3, nrow(vwport)), ]
##           date AMZN.Close AABA.Close IBM.Close AMZN.ret  AABA.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.0250588
## 3   0.9944994
## 253 1.0062230

Step 3: Calculate the Market Capitalization of Each Security in the Portfolio

# Construct Series of Calendar Days
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"

# Create Data Object with Daily Prices
PRICE.qtr <- vwport[, 1:4]
PRICE.qtr[c(1:3, nrow(PRICE.qtr)), ]
##           date AMZN.Close AABA.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

# Filling in Last Available Price on Non-trading Days
PRICE.qtr <- na.locf(merge(x = date, y = PRICE.qtr, by = "date", all.x = TRUE))
#all.x=T tells R to keep all the data in the "by" varialble that is available in x=date
#na.locf tells R to copy over the last available data in y 
#when there is a date in x that is not available in y
PRICE.qtr[c(1:3, nrow(PRICE.qtr)), ]
##           date AMZN.Close AABA.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

# Keep Only Prices at the End of Each Calendar Quarter
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 AABA.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

# Obtain Share Outstanding Data from SEC Filings
#http://www.sec.gov/edgar/searchedgar/companysearch.html
#Interactive Data / Financial Statements / Condensed Consolidated Balance Sheets
PRICE.qtr$AMZN.shout <- c(454000000, 455000000, 457000000, 458000000)
PRICE.qtr$AABA.shout <- c(1115233000, 1084766000, 1065046000, 1013059000)
PRICE.qtr$IBM.shout <- c(1117367676, 1108794396, 1095425823, 1085854383)
PRICE.qtr
##           date AMZN.Close AABA.Close IBM.Close AMZN.shout AABA.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   1117367676
## 91  1108794396
## 182 1095425823
## 274 1085854383

# Calculate Market Capitalization of Each Security
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"
##  $ AABA.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
##  $ AABA.shout: num  1.12e+09 1.08e+09 1.07e+09 1.01e+09
##  $ IBM.shout : num  1.12e+09 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$AABA.Close <- as.numeric(PRICE.qtr$AABA.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
##  $ AABA.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
##  $ AABA.shout: num  1.12e+09 1.08e+09 1.07e+09 1.01e+09
##  $ IBM.shout : num  1.12e+09 1.11e+09 1.10e+09 1.09e+09

weights <- PRICE.qtr
weights$AMZN.mcap <- weights$AMZN.Close * weights$AMZN.shout
weights$AABA.mcap <- weights$AABA.Close * weights$AABA.shout
weights$IBM.mcap <- weights$IBM.Close * weights$IBM.shout
weights
##           date AMZN.Close AABA.Close IBM.Close AMZN.shout AABA.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   AABA.mcap     IBM.mcap
## 1   1117367676 113894980000 22193136700 214031778338
## 91  1108794396 121252950000 25524543980 236505844667
## 182 1095425823 126904330000 26764605980 209346829034
## 274 1085854383 143189120000 33603167030 201078514644

# Calculate Quarter-end Aggregate Market Capitalization
weights$tot.mcap <- rowSums(weights[, 8:10])
weights
##           date AMZN.Close AABA.Close IBM.Close AMZN.shout AABA.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   AABA.mcap     IBM.mcap     tot.mcap
## 1   1117367676 113894980000 22193136700 214031778338 350119895038
## 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

weights$AMZN.wgt <- weights$AMZN.mcap / weights$tot.mcap
weights$AABA.wgt <- weights$AABA.mcap / weights$tot.mcap
weights$IBM.wgt <- weights$IBM.mcap / weights$tot.mcap
weights
##           date AMZN.Close AABA.Close IBM.Close AMZN.shout AABA.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   AABA.mcap     IBM.mcap     tot.mcap
## 1   1117367676 113894980000 22193136700 214031778338 350119895038
## 91  1108794396 121252950000 25524543980 236505844667 383283338647
## 182 1095425823 126904330000 26764605980 209346829034 363015765014
## 274 1085854383 143189120000 33603167030 201078514644 377870801674
##      AMZN.wgt   AABA.wgt   IBM.wgt
## 1   0.3253028 0.06338725 0.6113100
## 91  0.3163533 0.06659445 0.6170522
## 182 0.3495835 0.07372849 0.5766880
## 274 0.3789367 0.08892766 0.5321356

weights <- weights[, c(1, 12:14)]
weights
##           date  AMZN.wgt   AABA.wgt   IBM.wgt
## 1   2012-12-31 0.3253028 0.06338725 0.6113100
## 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

weights$date <- weights$date + 1 #since the weights are applicable at the start of the next Q
weights
##           date  AMZN.wgt   AABA.wgt   IBM.wgt
## 1   2013-01-01 0.3253028 0.06338725 0.6113100
## 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: Calculate the Quarterly VW Portfolio Values

q1.vw.wgt <- subset(weights, date == "2013-01-01") #I'm not sure why author took the long way
q2.vw.wgt <- subset(weights, date == "2013-04-01")
q3.vw.wgt <- subset(weights, date == "2013-07-01")
q4.vw.wgt <- subset(weights, date == "2013-10-01")
q1.vw.wgt
##         date  AMZN.wgt   AABA.wgt IBM.wgt
## 1 2013-01-01 0.3253028 0.06338725 0.61131
q2.vw.wgt
##          date  AMZN.wgt   AABA.wgt   IBM.wgt
## 91 2013-04-01 0.3163533 0.06659445 0.6170522
q3.vw.wgt
##           date  AMZN.wgt   AABA.wgt  IBM.wgt
## 182 2013-07-01 0.3495835 0.07372849 0.576688
q4.vw.wgt
##           date  AMZN.wgt   AABA.wgt   IBM.wgt
## 274 2013-10-01 0.3789367 0.08892766 0.5321356

Step 6: Create Pie Charts of the Weights

par(mfrow = c(2, 2))

Q1.pie.values <- as.numeric(q1.vw.wgt[, -1])
Q1.pie.labels <- names(q1.vw.wgt[, -1])
pie(Q1.pie.values,
    labels = Q1.pie.labels,
    col = c("black", "gray", "gray40"),
    main = "Q1 Value Weighting")

Q2.pie.values <- as.numeric(q2.vw.wgt[, -1])
Q2.pie.labels <- names(q1.vw.wgt[, -1])
pie(Q2.pie.values,
    labels = Q2.pie.labels,
    col = c("black", "gray", "gray40"),
    main = "Q2 Value Weighting")

Q3.pie.values <- as.numeric(q3.vw.wgt[, -1])
Q3.pie.labels <- c("Amazon", "Altaba", "IBM")
pct <- round(Q3.pie.values * 100)
Q3.pie.labels <- paste(Q3.pie.labels, pct) #Add Pct to Labels
Q3.pie.labels <- paste(Q3.pie.labels, "%", sep = "") #Add % Sign
pie(Q3.pie.values,
    labels = Q3.pie.labels,
    col = c("black", "gray", "gray40"),
    main = "Q3 Value Weighting")

Q4.pie.values <- as.numeric(q4.vw.wgt[, -1])
Q4.pie.labels <- c("Amazon", "Altaba", "IBM")
pct <- round(Q4.pie.values * 100)
Q4.pie.labels <- paste(Q4.pie.labels, pct) #Add Pct to Labels
Q4.pie.labels <- paste(Q4.pie.labels, "%", sep = "") #Add % Sign
pie(Q4.pie.values,
    labels = Q4.pie.labels,
    col = rainbow(length(Q4.pie.labels)), #to plot colored pie charts
    main = "Q4 Value Weighting")

Step 7: Calculate VW Portfolio Values for 1Q 2013

vw.q1 <- subset(vwport,
                vwport$date >= as.Date("2012-12-31") &
                vwport$date <= as.Date("2013-03-31"))
vw.q1[c(1:3, nrow(vw.q1)), ]
##          date AMZN.Close AABA.Close IBM.Close AMZN.ret  AABA.ret   IBM.ret
## 1  2012-12-31     250.87      19.90    191.55 1.023207 1.0205128 1.0090607
## 2  2013-01-02     257.31      20.08    196.35 1.025671 1.0090452 1.0250588
## 3  2013-01-03     258.48      19.78    195.27 1.004547 0.9850598 0.9944994
## 61 2013-03-28     266.49      23.53    213.30 1.004485 0.9974566 1.0114278

vw.q1 <- vw.q1[, c(1, 5:7)]
vw.q1[c(1:3, nrow(vw.q1)), ]
##          date AMZN.ret  AABA.ret   IBM.ret
## 1  2012-12-31 1.023207 1.0205128 1.0090607
## 2  2013-01-02 1.025671 1.0090452 1.0250588
## 3  2013-01-03 1.004547 0.9850598 0.9944994
## 61 2013-03-28 1.004485 0.9974566 1.0114278

names(vw.q1)[2:4] <- paste(c("AMZN", "AABA", "IBM"))
vw.q1[c(1:3, nrow(vw.q1)), ]
##          date     AMZN      AABA       IBM
## 1  2012-12-31 1.023207 1.0205128 1.0090607
## 2  2013-01-02 1.025671 1.0090452 1.0250588
## 3  2013-01-03 1.004547 0.9850598 0.9944994
## 61 2013-03-28 1.004485 0.9974566 1.0114278

vw.q1[1, 2:4] <- 1
vw.q1$AMZN <- cumprod(vw.q1$AMZN) 
vw.q1$AABA <- cumprod(vw.q1$AABA)
vw.q1$IBM <- cumprod(vw.q1$IBM)
vw.q1[c(1:3, nrow(vw.q1)), ]
##          date     AMZN      AABA      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.019420
## 61 2013-03-28 1.062263 1.1824121 1.118235

vw.q1$AMZN.idx <- vw.q1$AMZN * q1.vw.wgt$AMZN.wgt #Apply the Q-end weights; note 
# that q1.vw.wgt$AMZN.wgt is a scalar
vw.q1$AABA.idx <- vw.q1$AABA * q1.vw.wgt$AABA.wgt
vw.q1$IBM.idx <- vw.q1$IBM * q1.vw.wgt$IBM.wgt
vw.q1[c(1:3, nrow(vw.q1)), ]
##          date     AMZN      AABA      IBM  AMZN.idx   AABA.idx   IBM.idx
## 1  2012-12-31 1.000000 1.0000000 1.000000 0.3253028 0.06338725 0.6113100
## 2  2013-01-02 1.025671 1.0090452 1.025059 0.3336535 0.06396060 0.6266287
## 3  2013-01-03 1.030335 0.9939699 1.019420 0.3351707 0.06300502 0.6231819
## 61 2013-03-28 1.062263 1.1824121 1.118235 0.3455572 0.07494985 0.6835879
#idx = daily gross returns * quarterly weight
#weight is based on market capitalization
#So larger firms would have a greater influence on portfolio returns

q1.vw.val <- data.frame(rowSums(vw.q1[, 5:7])) #Calculate the daily portfolio values
q1.vw.val[c(1:3, nrow(q1.vw.val)), ]
## [1] 1.000000 1.024243 1.021358 1.104095
names(q1.vw.val) <- paste("port.val")
q1.vw.val$date <- vw.q1$date
q1.vw.val[c(1:3, nrow(q1.vw.val)), ]
##    port.val       date
## 1  1.000000 2012-12-31
## 2  1.024243 2013-01-02
## 3  1.021358 2013-01-03
## 61 1.104095 2013-03-28

q2.vw.inv <- q1.vw.val[nrow(q1.vw.val), 1]
q2.vw.inv
## [1] 1.104095

Step 8: Calculate VW Portfolio Values for 2Q 2013

vw.q2 <- subset(vwport,
                vwport$date >= "2013-04-01" &
                vwport$date <= "2013-06-30")
vw.q2[c(1:3, nrow(vw.q2)), ]
##           date AMZN.Close AABA.Close IBM.Close  AMZN.ret  AABA.ret
## 62  2013-04-01     261.61      23.50    212.38 0.9816878 0.9987250
## 63  2013-04-02     263.32      23.78    214.36 1.0065365 1.0119149
## 64  2013-04-03     259.03      23.38    212.66 0.9837080 0.9831791
## 125 2013-06-28     277.69      25.13    191.11 1.0005045 0.9866510
##       IBM.ret
## 62  0.9956868
## 63  1.0093230
## 64  0.9920694
## 125 0.9767953

vw.q2 <- vw.q2[, c(1, 5:7)]
vw.q2[c(1:3, nrow(vw.q2)), ]
##           date  AMZN.ret  AABA.ret   IBM.ret
## 62  2013-04-01 0.9816878 0.9987250 0.9956868
## 63  2013-04-02 1.0065365 1.0119149 1.0093230
## 64  2013-04-03 0.9837080 0.9831791 0.9920694
## 125 2013-06-28 1.0005045 0.9866510 0.9767953

names(vw.q2)[2:4] <- paste(c("AMZN", "AABA", "IBM"))
vw.q2[c(1:3, nrow(vw.q2)), ]
##           date      AMZN      AABA       IBM
## 62  2013-04-01 0.9816878 0.9987250 0.9956868
## 63  2013-04-02 1.0065365 1.0119149 1.0093230
## 64  2013-04-03 0.9837080 0.9831791 0.9920694
## 125 2013-06-28 1.0005045 0.9866510 0.9767953

#vw.q2[1, 2:4] <- 1 #difference from Q1
vw.q2$AMZN <- cumprod(vw.q2$AMZN)
vw.q2$AABA <- cumprod(vw.q2$AABA)
vw.q2$IBM <- cumprod(vw.q2$IBM)
vw.q2[c(1:3, nrow(vw.q2)), ]
##           date      AMZN      AABA       IBM
## 62  2013-04-01 0.9816878 0.9987250 0.9956868
## 63  2013-04-02 0.9881047 1.0106247 1.0049696
## 64  2013-04-03 0.9720065 0.9936251 0.9969995
## 125 2013-06-28 1.0420279 1.0679982 0.9001678

vw.q2$AMZN.ind <- (q2.vw.inv * q2.vw.wgt$AMZN.wgt) * vw.q2$AMZN #Apply weight
vw.q2$AABA.ind <- (q2.vw.inv * q2.vw.wgt$AABA.wgt) * vw.q2$AABA
vw.q2$IBM.ind <- (q2.vw.inv * q2.vw.wgt$IBM.wgt) * vw.q2$IBM
vw.q2[c(1:3, nrow(vw.q2)), ]
##           date      AMZN      AABA       IBM  AMZN.ind   AABA.ind
## 62  2013-04-01 0.9816878 0.9987250 0.9956868 0.3428879 0.07343285
## 63  2013-04-02 0.9881047 1.0106247 1.0049696 0.3451292 0.07430780
## 64  2013-04-03 0.9720065 0.9936251 0.9969995 0.3395064 0.07305787
## 125 2013-06-28 1.0420279 1.0679982 0.9001678 0.3639638 0.07852628
##       IBM.ind
## 62  0.6783457
## 63  0.6846700
## 64  0.6792401
## 125 0.6132702

q2.vw.val <- data.frame(rowSums(vw.q2[, 5:7]))
q2.vw.val[c(1:3, nrow(q2.vw.val)), ]
## [1] 1.094667 1.104107 1.091804 1.055760

names(q2.vw.val) <- paste("port.val")
q2.vw.val[c(1:3, nrow(q2.vw.val)), ]
## [1] 1.094667 1.104107 1.091804 1.055760

q2.vw.val$date <- vw.q2$date
q2.vw.val[c(1:3, nrow(q2.vw.val)), ]
##     port.val       date
## 62  1.094667 2013-04-01
## 63  1.104107 2013-04-02
## 64  1.091804 2013-04-03
## 125 1.055760 2013-06-28

q3.vw.inv <- q2.vw.val[nrow(q2.vw.val), 1]
q3.vw.inv
## [1] 1.05576
#$1.104 at the end of Q1 and $1.056 by the end of Q2
#it doesn't mean that the portfolio grew 5.6% during Q2 but 5.6% during Q1-Q2
#b/c it's a cumulative measure

Step 9: Calculate VW Portfolio Values for 3Q 2013

vw.q3 <- subset(vwport,
                vwport$date >= "2013-07-01" &
                vwport$date <= "2013-09-30")
vw.q3[c(1:3, nrow(vw.q3)), ]
##           date AMZN.Close AABA.Close IBM.Close  AMZN.ret  AABA.ret
## 126 2013-07-01     282.10      25.24    191.28 1.0158810 1.0043773
## 127 2013-07-02     283.73      24.99    191.50 1.0057781 0.9900951
## 128 2013-07-03     284.03      25.59    193.25 1.0010573 1.0240096
## 189 2013-09-30     312.64      33.17    185.18 0.9893358 0.9886736
##       IBM.ret
## 126 1.0008894
## 127 1.0011501
## 128 1.0091385
## 189 0.9906917

vw.q3 <- vw.q3[, c(1, 5:7)]
vw.q3[c(1:3, nrow(vw.q3)), ]
##           date  AMZN.ret  AABA.ret   IBM.ret
## 126 2013-07-01 1.0158810 1.0043773 1.0008894
## 127 2013-07-02 1.0057781 0.9900951 1.0011501
## 128 2013-07-03 1.0010573 1.0240096 1.0091385
## 189 2013-09-30 0.9893358 0.9886736 0.9906917

names(vw.q3)[2:4] <- paste(c("AMZN", "AABA", "IBM"))
vw.q3[c(1:3, nrow(vw.q3)), ]
##           date      AMZN      AABA       IBM
## 126 2013-07-01 1.0158810 1.0043773 1.0008894
## 127 2013-07-02 1.0057781 0.9900951 1.0011501
## 128 2013-07-03 1.0010573 1.0240096 1.0091385
## 189 2013-09-30 0.9893358 0.9886736 0.9906917

#vw.q3[1, 2:4] <- 1 #difference from Q1
vw.q3$AMZN <- cumprod(vw.q3$AMZN)
vw.q3$AABA <- cumprod(vw.q3$AABA)
vw.q3$IBM <- cumprod(vw.q3$IBM)
vw.q3[c(1:3, nrow(vw.q3)), ]
##           date     AMZN     AABA       IBM
## 126 2013-07-01 1.015881 1.004377 1.0008894
## 127 2013-07-02 1.021751 0.994429 1.0020405
## 128 2013-07-03 1.022831 1.018305 1.0111977
## 189 2013-09-30 1.125860 1.319936 0.9738145

vw.q3$AMZN.ind <- (q3.vw.inv * q3.vw.wgt$AMZN.wgt) * vw.q3$AMZN #Apply weight
vw.q3$AABA.ind <- (q3.vw.inv * q3.vw.wgt$AABA.wgt) * vw.q3$AABA
vw.q3$IBM.ind <- (q3.vw.inv * q3.vw.wgt$IBM.wgt) * vw.q3$IBM
vw.q3[c(1:3, nrow(vw.q3)), ]
##           date     AMZN     AABA       IBM  AMZN.ind   AABA.ind   IBM.ind
## 126 2013-07-01 1.015881 1.004377 1.0008894 0.3749377 0.07818034 0.6093857
## 127 2013-07-02 1.021751 0.994429 1.0020405 0.3771041 0.07740597 0.6100866
## 128 2013-07-03 1.022831 1.018305 1.0111977 0.3775028 0.07926446 0.6156619
## 189 2013-09-30 1.125860 1.319936 0.9738145 0.4155283 0.10274333 0.5929013

q3.vw.val <- data.frame(rowSums(vw.q3[, 5:7]))
q3.vw.val[c(1:3, nrow(q3.vw.val)), ]
## [1] 1.062504 1.064597 1.072429 1.111173

names(q3.vw.val) <- paste("port.val")
q3.vw.val[c(1:3, nrow(q3.vw.val)), ]
## [1] 1.062504 1.064597 1.072429 1.111173

q3.vw.val$date <- vw.q3$date
q3.vw.val[c(1:3, nrow(q3.vw.val)), ]
##     port.val       date
## 126 1.062504 2013-07-01
## 127 1.064597 2013-07-02
## 128 1.072429 2013-07-03
## 189 1.111173 2013-09-30

q4.vw.inv <- q3.vw.val[nrow(q3.vw.val), 1]
q4.vw.inv
## [1] 1.111173
#$1.104 at the end of Q1 and $1.111 by the end of Q3
#it doesn't mean that the portfolio grew 11.1% during q3 but 11.1% during Q1-Q3
#b/c it's a cumulative measure

Step 10: Calculate VW Portfolio Values for 4Q 2013

vw.q4 <- subset(vwport,
                vwport$date >= "2013-10-01" &
                  vwport$date <= "2013-12-31")
vw.q4[c(1:3, nrow(vw.q4)), ]
##           date AMZN.Close AABA.Close IBM.Close  AMZN.ret  AABA.ret
## 190 2013-10-01     320.95      34.31    186.38 1.0265801 1.0343685
## 191 2013-10-02     320.51      34.14    184.96 0.9986291 0.9950451
## 192 2013-10-03     314.76      33.88    183.86 0.9820598 0.9923844
## 253 2013-12-31     398.79      40.44    187.57 1.0137784 1.0059701
##       IBM.ret
## 190 1.0064803
## 191 0.9923810
## 192 0.9940527
## 253 1.0062230

vw.q4 <- vw.q4[, c(1, 5:7)]
vw.q4[c(1:3, nrow(vw.q4)), ]
##           date  AMZN.ret  AABA.ret   IBM.ret
## 190 2013-10-01 1.0265801 1.0343685 1.0064803
## 191 2013-10-02 0.9986291 0.9950451 0.9923810
## 192 2013-10-03 0.9820598 0.9923844 0.9940527
## 253 2013-12-31 1.0137784 1.0059701 1.0062230

names(vw.q4)[2:4] <- paste(c("AMZN", "AABA", "IBM"))
vw.q4[c(1:3, nrow(vw.q4)), ]
##           date      AMZN      AABA       IBM
## 190 2013-10-01 1.0265801 1.0343685 1.0064803
## 191 2013-10-02 0.9986291 0.9950451 0.9923810
## 192 2013-10-03 0.9820598 0.9923844 0.9940527
## 253 2013-12-31 1.0137784 1.0059701 1.0062230

#vw.q4[1, 2:4] <- 1 #difference from Q1
vw.q4$AMZN <- cumprod(vw.q4$AMZN)
vw.q4$AABA <- cumprod(vw.q4$AABA)
vw.q4$IBM <- cumprod(vw.q4$IBM)
vw.q4[c(1:3, nrow(vw.q4)), ]
##           date     AMZN     AABA       IBM
## 190 2013-10-01 1.026580 1.034368 1.0064803
## 191 2013-10-02 1.025173 1.029243 0.9988119
## 192 2013-10-03 1.006781 1.021405 0.9928717
## 253 2013-12-31 1.275557 1.219174 1.0183460

vw.q4$AMZN.ind <- (q4.vw.inv * q4.vw.wgt$AMZN.wgt) * vw.q4$AMZN #Apply weight
vw.q4$AABA.ind <- (q4.vw.inv * q4.vw.wgt$AABA.wgt) * vw.q4$AABA
vw.q4$IBM.ind <- (q4.vw.inv * q4.vw.wgt$IBM.wgt) * vw.q4$IBM
vw.q4[c(1:3, nrow(vw.q4)), ]
##           date     AMZN     AABA       IBM  AMZN.ind  AABA.ind   IBM.ind
## 190 2013-10-01 1.026580 1.034368 1.0064803 0.4322561 0.1022101 0.5951265
## 191 2013-10-02 1.025173 1.029243 0.9988119 0.4316635 0.1017037 0.5905922
## 192 2013-10-03 1.006781 1.021405 0.9928717 0.4239194 0.1009291 0.5870798
## 253 2013-12-31 1.275557 1.219174 1.0183460 0.5370912 0.1204715 0.6021426

q4.vw.val <- data.frame(rowSums(vw.q4[, 5:7]))
q4.vw.val[c(1:3, nrow(q4.vw.val)), ]
## [1] 1.129593 1.123959 1.111928 1.259705

names(q4.vw.val) <- paste("port.val")
q4.vw.val[c(1:3, nrow(q4.vw.val)), ]
## [1] 1.129593 1.123959 1.111928 1.259705

q4.vw.val$date <- vw.q4$date
q4.vw.val[c(1:3, nrow(q4.vw.val)), ]
##     port.val       date
## 190 1.129593 2013-10-01
## 191 1.123959 2013-10-02
## 192 1.111928 2013-10-03
## 253 1.259705 2013-12-31
#$1.104 at the end of Q1 and $1.259 by the end of Q4
#it doesn't mean that the portfolio grew 25.9% during Q4 but 25.9% during Q1-Q4
#b/c it's a cumulative measure

Step 11: Combine Quarterly VW Portfolio Values into One Data Object

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

3.3.3 Normalized EW and VW Portfolio Price Chart

Compare the performance of EW and VW portfolio from 12/31/2012 to 12/31/2013

Step 1: Combine the Data

port.val <- merge(vw.portval, ew.portval, by = "date")
port.val[c(1:3, nrow(port.val)), ]
##           date port.val.x port.val.y
## 1   2012-12-31   1.000000   1.000000
## 2   2013-01-02   1.024243   1.019925
## 3   2013-01-03   1.021358   1.014575
## 253 2013-12-31   1.259705   1.501374

Step 2: Rename the Variables

names(port.val)[2:3] <- paste(c("VW.cum", "EW.cum"))
port.val[c(1:3, nrow(port.val)), ]
##           date   VW.cum   EW.cum
## 1   2012-12-31 1.000000 1.000000
## 2   2013-01-02 1.024243 1.019925
## 3   2013-01-03 1.021358 1.014575
## 253 2013-12-31 1.259705 1.501374

Step 3: Plot the Data

par(mfrow = c(1, 1))
y.range <- range(port.val[, 2:3])
y.range
## [1] 1.000000 1.506584
plot(port.val$EW.cum,
     xlab = "Date",
     ylab = "Value of Investment",
     ylim = y.range,
     type = "l",
     lty = 1,
     main = "Value of R1 Investment in Equal-Weighted and
          Value-Weighted Portfolio of AMZN, AABA, and IBM
          December 31, 2012 - December 31, 2013")
lines(port.val$VW.cum, lty = 2)
abline(h = 1, lty = 1)
legend("topleft",
       c("Equal-Weighted Portfolio", "Value-Weighted Portfolio"), #typo in the textbook
       lty = c(1, 2))

3.3.4 Saving Benchmark Portfolio Returns into a CSV File

Net returns as well as cumulative returns

Step 1: Convert the Data into an xts Object

# This is to appropriately take the lag of the portfolio value
port.xts <- xts(port.val[, 2:3], order.by = port.val[, 1])
port.xts[c(1:3, nrow(port.xts)), ]
##              VW.cum   EW.cum
## 2012-12-31 1.000000 1.000000
## 2013-01-02 1.024243 1.019925
## 2013-01-03 1.021358 1.014575
## 2013-12-31 1.259705 1.501374

port.xts$Lag.VW <- Lag(port.xts$VW.cum, k = 1)
port.xts$Lag.EW <- Lag(port.xts$EW.cum, k = 1)
port.xts[c(1:3, nrow(port.xts)), ]
##              VW.cum   EW.cum   Lag.VW   Lag.EW
## 2012-12-31 1.000000 1.000000       NA       NA
## 2013-01-02 1.024243 1.019925 1.000000 1.000000
## 2013-01-03 1.021358 1.014575 1.024243 1.019925
## 2013-12-31 1.259705 1.501374 1.247967 1.488182

Step 2: Create EW and VW Returns

port.xts$VW.ret <- port.xts$VW.cum / port.xts$Lag.VW - 1
port.xts$EW.ret <- port.xts$EW.cum / port.xts$Lag.EW - 1
port.xts[c(1:3, nrow(port.xts)), ]
##              VW.cum   EW.cum   Lag.VW   Lag.EW       VW.ret      EW.ret
## 2012-12-31 1.000000 1.000000       NA       NA           NA          NA
## 2013-01-02 1.024243 1.019925 1.000000 1.000000  0.024242817  0.01992492
## 2013-01-03 1.021358 1.014575 1.024243 1.019925 -0.002816943 -0.00524545
## 2013-12-31 1.259705 1.501374 1.247967 1.488182  0.009406173  0.00886496

Step 3: Clean up the Data

Port.Ret <- port.xts[, c(1, 2, 5, 6)]
Port.Ret[c(1:3, nrow(port.xts)), ]
##              VW.cum   EW.cum       VW.ret      EW.ret
## 2012-12-31 1.000000 1.000000           NA          NA
## 2013-01-02 1.024243 1.019925  0.024242817  0.01992492
## 2013-01-03 1.021358 1.014575 -0.002816943 -0.00524545
## 2013-12-31 1.259705 1.501374  0.009406173  0.00886496

Step 4: Create a Date Variable in the Data Object

csv.port <- cbind(data.frame(index(Port.Ret)), data.frame(Port.Ret))
names(csv.port)[1] <- paste("date")
csv.port[c(1:3, nrow(port.xts)), ]
##                  date   VW.cum   EW.cum       VW.ret      EW.ret
## 2012-12-31 2012-12-31 1.000000 1.000000           NA          NA
## 2013-01-02 2013-01-02 1.024243 1.019925  0.024242817  0.01992492
## 2013-01-03 2013-01-03 1.021358 1.014575 -0.002816943 -0.00524545
## 2013-12-31 2013-12-31 1.259705 1.501374  0.009406173  0.00886496

Step 5: Replace Index with Observation Numbers

rownames(csv.port) <- seq(1:nrow(csv.port))
csv.port[c(1:3, nrow(port.xts)), ]
##           date   VW.cum   EW.cum       VW.ret      EW.ret
## 1   2012-12-31 1.000000 1.000000           NA          NA
## 2   2013-01-02 1.024243 1.019925  0.024242817  0.01992492
## 3   2013-01-03 1.021358 1.014575 -0.002816943 -0.00524545
## 253 2013-12-31 1.259705 1.501374  0.009406173  0.00886496

Step 6: Save the Data to a CSV File

#write.csv(csv.port, "Hypothetical Portfolio (Daily).csv")