Chapter 3: 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 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 = "2016-12-30", to = "2017-06-30", auto.assign = FALSE)
data.MSFT <- getSymbols("MSFT", from = "2016-12-30", to = "2017-06-30", auto.assign = FALSE)
data.AAPL <- getSymbols("AAPL", from = "2016-12-30", to = "2017-06-30", auto.assign = FALSE)
data.TSLA <- getSymbols("TSLA", from = "2016-12-30", to = "2017-06-30", 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. 

Step 1: Importing the Price Data

data.AMZN[c(1:3, nrow(data.AMZN)), ]
##            AMZN.Open AMZN.High AMZN.Low AMZN.Close AMZN.Volume
## 2016-12-30    766.47    767.40   748.28     749.87     4139400
## 2017-01-03    757.92    758.76   747.70     753.67     3521100
## 2017-01-04    758.39    759.68   754.20     757.18     2510500
## 2017-06-29    979.00    987.56   965.25     975.93     4303000
##            AMZN.Adjusted
## 2016-12-30        749.87
## 2017-01-03        753.67
## 2017-01-04        757.18
## 2017-06-29        975.93
data.MSFT[c(1:3, nrow(data.MSFT)), ]
##            MSFT.Open MSFT.High MSFT.Low MSFT.Close MSFT.Volume
## 2016-12-30     62.96     62.99    62.03      62.14    25579900
## 2017-01-03     62.79     62.84    62.13      62.58    20694100
## 2017-01-04     62.48     62.75    62.12      62.30    21340000
## 2017-06-29     69.38     69.49    68.09      68.49    28918700
##            MSFT.Adjusted
## 2016-12-30      60.78280
## 2017-01-03      61.21319
## 2017-01-04      60.93930
## 2017-06-29      67.78660
data.AAPL[c(1:3, nrow(data.AAPL)), ]
##            AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume
## 2016-12-30    116.65    117.20   115.43     115.82    30586300
## 2017-01-03    115.80    116.33   114.76     116.15    28781900
## 2017-01-04    115.85    116.51   115.75     116.02    21118100
## 2017-06-29    144.71    145.13   142.28     143.68    31499400
##            AAPL.Adjusted
## 2016-12-30      113.9870
## 2017-01-03      114.3118
## 2017-01-04      114.1838
## 2017-06-29      142.6053
data.TSLA[c(1:3, nrow(data.TSLA)), ]
##            TSLA.Open TSLA.High TSLA.Low TSLA.Close TSLA.Volume
## 2016-12-30    216.30    217.50   211.68     213.69     4642600
## 2017-01-03    214.86    220.33   210.96     216.99     5923300
## 2017-01-04    214.75    228.00   214.31     226.99    11213500
## 2017-06-29    370.61    371.00   354.10     360.75     8221000
##            TSLA.Adjusted
## 2016-12-30        213.69
## 2017-01-03        216.99
## 2017-01-04        226.99
## 2017-06-29        360.75

Step 2: Create Object with Only the Relevant Data

port <- data.AMZN[, c(4, 6)]
port <- merge(port, data.MSFT[, c(4, 6)])
port <- merge(port, data.AAPL[, c(4, 6)])
port <- merge(port, data.TSLA[, c(4, 6)])
#port <- cbind(port, data.MSFT[, c(4, 6)], data.AAPL[, c(4, 6)], data.TSLA[, c(4, 6)])
port[c(1:3, nrow(port)), ]
##            AMZN.Close AMZN.Adjusted MSFT.Close MSFT.Adjusted AAPL.Close
## 2016-12-30     749.87        749.87      62.14      60.78280     115.82
## 2017-01-03     753.67        753.67      62.58      61.21319     116.15
## 2017-01-04     757.18        757.18      62.30      60.93930     116.02
## 2017-06-29     975.93        975.93      68.49      67.78660     143.68
##            AAPL.Adjusted TSLA.Close TSLA.Adjusted
## 2016-12-30      113.9870     213.69        213.69
## 2017-01-03      114.3118     216.99        216.99
## 2017-01-04      114.1838     226.99        226.99
## 2017-06-29      142.6053     360.75        360.75

Step 3: Calculate Returns of Each Security

port$AMZN.ret <- Delt(port$AMZN.Adjusted)
port$MSFT.ret <- Delt(port$MSFT.Adjusted)
port$AAPL.ret <- Delt(port$AAPL.Adjusted)
port$TSLA.ret <- Delt(port$TSLA.Adjusted)
port[c(1:3, nrow(port)), ]
##            AMZN.Close AMZN.Adjusted MSFT.Close MSFT.Adjusted AAPL.Close
## 2016-12-30     749.87        749.87      62.14      60.78280     115.82
## 2017-01-03     753.67        753.67      62.58      61.21319     116.15
## 2017-01-04     757.18        757.18      62.30      60.93930     116.02
## 2017-06-29     975.93        975.93      68.49      67.78660     143.68
##            AAPL.Adjusted TSLA.Close TSLA.Adjusted     AMZN.ret
## 2016-12-30      113.9870     213.69        213.69           NA
## 2017-01-03      114.3118     216.99        216.99  0.005067529
## 2017-01-04      114.1838     226.99        226.99  0.004657224
## 2017-06-29      142.6053     360.75        360.75 -0.014540632
##                MSFT.ret     AAPL.ret    TSLA.ret
## 2016-12-30           NA           NA          NA
## 2017-01-03  0.007080902  0.002849238  0.01544295
## 2017-01-04 -0.004474330 -0.001119264  0.04608507
## 2017-06-29 -0.018767921 -0.014743251 -0.02825663

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 MSFT.Close MSFT.Adjusted
## 2016-12-30 2016-12-30     749.87        749.87      62.14      60.78280
## 2017-01-03 2017-01-03     753.67        753.67      62.58      61.21319
## 2017-01-04 2017-01-04     757.18        757.18      62.30      60.93930
## 2017-06-29 2017-06-29     975.93        975.93      68.49      67.78660
##            AAPL.Close AAPL.Adjusted TSLA.Close TSLA.Adjusted     AMZN.ret
## 2016-12-30     115.82      113.9870     213.69        213.69           NA
## 2017-01-03     116.15      114.3118     216.99        216.99  0.005067529
## 2017-01-04     116.02      114.1838     226.99        226.99  0.004657224
## 2017-06-29     143.68      142.6053     360.75        360.75 -0.014540632
##                MSFT.ret     AAPL.ret    TSLA.ret
## 2016-12-30           NA           NA          NA
## 2017-01-03  0.007080902  0.002849238  0.01544295
## 2017-01-04 -0.004474330 -0.001119264  0.04608507
## 2017-06-29 -0.018767921 -0.014743251 -0.02825663

port <- subset(port,
               port$date >= "2016-12-30" &
               port$date <= "2017-12-29")
port[c(1:3, nrow(port)), ]
##                  date AMZN.Close AMZN.Adjusted MSFT.Close MSFT.Adjusted
## 2016-12-30 2016-12-30     749.87        749.87      62.14      60.78280
## 2017-01-03 2017-01-03     753.67        753.67      62.58      61.21319
## 2017-01-04 2017-01-04     757.18        757.18      62.30      60.93930
## 2017-06-29 2017-06-29     975.93        975.93      68.49      67.78660
##            AAPL.Close AAPL.Adjusted TSLA.Close TSLA.Adjusted     AMZN.ret
## 2016-12-30     115.82      113.9870     213.69        213.69           NA
## 2017-01-03     116.15      114.3118     216.99        216.99  0.005067529
## 2017-01-04     116.02      114.1838     226.99        226.99  0.004657224
## 2017-06-29     143.68      142.6053     360.75        360.75 -0.014540632
##                MSFT.ret     AAPL.ret    TSLA.ret
## 2016-12-30           NA           NA          NA
## 2017-01-03  0.007080902  0.002849238  0.01544295
## 2017-01-04 -0.004474330 -0.001119264  0.04608507
## 2017-06-29 -0.018767921 -0.014743251 -0.02825663

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, 10:13)]
ewport[c(1:3, nrow(ewport)), ]
##                  date     AMZN.ret     MSFT.ret     AAPL.ret    TSLA.ret
## 2016-12-30 2016-12-30           NA           NA           NA          NA
## 2017-01-03 2017-01-03  0.005067529  0.007080902  0.002849238  0.01544295
## 2017-01-04 2017-01-04  0.004657224 -0.004474330 -0.001119264  0.04608507
## 2017-06-29 2017-06-29 -0.014540632 -0.018767921 -0.014743251 -0.02825663

names(ewport)[2:5] <- c("AMZN", "MSFT", "AAPL", "TSLA")
rownames(ewport) <- seq(1, nrow(ewport), 1)
ewport[c(1:3, nrow(ewport)), ]
##           date         AMZN         MSFT         AAPL        TSLA
## 1   2016-12-30           NA           NA           NA          NA
## 2   2017-01-03  0.005067529  0.007080902  0.002849238  0.01544295
## 3   2017-01-04  0.004657224 -0.004474330 -0.001119264  0.04608507
## 125 2017-06-29 -0.014540632 -0.018767921 -0.014743251 -0.02825663

Step 2: Convert Net Returns to Gross Returns

ewport[2:5] <- ewport[2:5] + 1
ewport[c(1:3, nrow(ewport)), ]
##           date      AMZN      MSFT      AAPL      TSLA
## 1   2016-12-30        NA        NA        NA        NA
## 2   2017-01-03 1.0050675 1.0070809 1.0028492 1.0154429
## 3   2017-01-04 1.0046572 0.9955257 0.9988807 1.0460851
## 125 2017-06-29 0.9854594 0.9812321 0.9852567 0.9717434

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 >= "2016-12-30" &
               ewport$date <= "2017-06-29")
ewq1[c(1:3, nrow(ewq1)), ]
##           date      AMZN      MSFT      AAPL      TSLA
## 1   2016-12-30        NA        NA        NA        NA
## 2   2017-01-03 1.0050675 1.0070809 1.0028492 1.0154429
## 3   2017-01-04 1.0046572 0.9955257 0.9988807 1.0460851
## 125 2017-06-29 0.9854594 0.9812321 0.9852567 0.9717434

# Calculate the cumulative gross returns fro each security for Q1
ewq1[1, 2:5] <- 1
ewq1[2:5] <- cumprod(ewq1[2:5])
ewq1[c(1:3, nrow(ewq1)), ]
##           date     AMZN     MSFT     AAPL     TSLA
## 1   2016-12-30 1.000000 1.000000 1.000000 1.000000
## 2   2017-01-03 1.005068 1.007081 1.002849 1.015443
## 3   2017-01-04 1.009748 1.002575 1.001727 1.062240
## 125 2017-06-29 1.301466 1.115227 1.251067 1.688193

# Calculate the index value for each security for Q1
num.sec <- 3
ewq1$AMZN.ind <- ewq1$AMZN / num.sec
ewq1$MSFT.ind <- ewq1$MSFT / num.sec
ewq1$AAPL.ind <- ewq1$AAPL / num.sec
ewq1$TSLA.ind <- ewq1$TSLA / num.sec
ewq1[c(1:3, nrow(ewq1)), ]
##           date     AMZN     MSFT     AAPL     TSLA  AMZN.ind  MSFT.ind
## 1   2016-12-30 1.000000 1.000000 1.000000 1.000000 0.3333333 0.3333333
## 2   2017-01-03 1.005068 1.007081 1.002849 1.015443 0.3350225 0.3356936
## 3   2017-01-04 1.009748 1.002575 1.001727 1.062240 0.3365828 0.3341916
## 125 2017-06-29 1.301466 1.115227 1.251067 1.688193 0.4338219 0.3717422
##      AAPL.ind  TSLA.ind
## 1   0.3333333 0.3333333
## 2   0.3342831 0.3384810
## 3   0.3339089 0.3540799
## 125 0.4170222 0.5627311

# Calculate the agrregate portfolio value on each day
q1.val <- data.frame(rowSums(ewq1[, 6:9]))
q1.val[c(1:3, nrow(q1.val)), ]
## [1] 1.333333 1.343480 1.358763 1.785317
names(q1.val) <- paste("port.val")
q1.val$date <- ewq1$date
q1.val[c(1:3, nrow(q1.val)), ]
##     port.val       date
## 1   1.333333 2016-12-30
## 2   1.343480 2017-01-03
## 3   1.358763 2017-01-04
## 125 1.785317 2017-06-29

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

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 >= "2017-04-01" &
               ewport$date <= "2017-06-30")
ewq2[c(1:3, nrow(ewq2)), ]
##           date      AMZN      MSFT      AAPL      TSLA
## 64  2017-04-03 1.0056061 0.9952930 1.0002784 1.0726554
## 65  2017-04-04 1.0171843 1.0027460 1.0074461 1.0173523
## 66  2017-04-05 1.0027017 0.9974135 0.9948194 0.9713533
## 125 2017-06-29 0.9854594 0.9812321 0.9852567 0.9717434

# Calculate the cumulative gross returns fro each security for Q2
#ewq2[1, 2:4] <- 1 This is the difference from Q1
ewq2[2:5] <- cumprod(ewq2[2:5])
ewq2[c(1:3, nrow(ewq2)), ]
##           date     AMZN      MSFT     AAPL     TSLA
## 64  2017-04-03 1.005606 0.9952930 1.000278 1.072655
## 65  2017-04-04 1.022887 0.9980261 1.007727 1.091269
## 66  2017-04-05 1.025650 0.9954448 1.002506 1.060007
## 125 2017-06-29 1.100830 1.0458940 1.004267 1.296263

# Calculate the index value for each security for Q2
ewq2$AMZN.ind <- (q2.inv / num.sec) * ewq2$AMZN #a difference from Q1
ewq2$MSFT.ind <- (q2.inv / num.sec) * ewq2$MSFT 
ewq2$AAPL.ind <- (q2.inv / num.sec) * ewq2$AAPL 
ewq2$TSLA.ind <- (q2.inv / num.sec) * ewq2$TSLA
ewq2[c(1:3, nrow(ewq2)), ]
##           date     AMZN      MSFT     AAPL     TSLA  AMZN.ind  MSFT.ind
## 64  2017-04-03 1.005606 0.9952930 1.000278 1.072655 0.5984420 0.5923046
## 65  2017-04-04 1.022887 0.9980261 1.007727 1.091269 0.6087258 0.5939311
## 66  2017-04-05 1.025650 0.9954448 1.002506 1.060007 0.6103705 0.5923949
## 125 2017-06-29 1.100830 1.0458940 1.004267 1.296263 0.6551104 0.6224176
##      AAPL.ind  TSLA.ind
## 64  0.5952715 0.6383435
## 65  0.5997039 0.6494202
## 66  0.5965971 0.6308164
## 125 0.5976452 0.7714137

# Calculate the agrregate portfolio value on each day
q2.val <- data.frame(rowSums(ewq2[, 6:9]))
q2.val[c(1:3, nrow(q2.val)), ]
## [1] 2.424362 2.451781 2.430179 2.646587
names(q2.val) <- paste("port.val")
q2.val$date <- ewq2$date
q2.val[c(1:3, nrow(q2.val)), ]
##     port.val       date
## 64  2.424362 2017-04-03
## 65  2.451781 2017-04-04
## 66  2.430179 2017-04-05
## 125 2.646587 2017-06-29

#$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 7: Combine Quarterly EW Portfolio Values into One Data Object

ew.portval <- rbind(q1.val, q2.val)
ew.portval[c(1:3, nrow(ew.portval)), ]
##      port.val       date
## 1    1.333333 2016-12-30
## 2    1.343480 2017-01-03
## 3    1.358763 2017-01-04
## 1251 2.646587 2017-06-29

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:13)] #port is from 3.3 Constructing Benchmark Portfolio Returns
vwport[c(1:3, nrow(vwport)), ]
##                  date AMZN.Close MSFT.Close AAPL.Close TSLA.Close
## 2016-12-30 2016-12-30     749.87      62.14     115.82     213.69
## 2017-01-03 2017-01-03     753.67      62.58     116.15     216.99
## 2017-01-04 2017-01-04     757.18      62.30     116.02     226.99
## 2017-06-29 2017-06-29     975.93      68.49     143.68     360.75
##                AMZN.ret     MSFT.ret     AAPL.ret    TSLA.ret
## 2016-12-30           NA           NA           NA          NA
## 2017-01-03  0.005067529  0.007080902  0.002849238  0.01544295
## 2017-01-04  0.004657224 -0.004474330 -0.001119264  0.04608507
## 2017-06-29 -0.014540632 -0.018767921 -0.014743251 -0.02825663
rownames(vwport) <- seq(1:nrow(vwport))
vwport[c(1:3, nrow(vwport)), ]
##           date AMZN.Close MSFT.Close AAPL.Close TSLA.Close     AMZN.ret
## 1   2016-12-30     749.87      62.14     115.82     213.69           NA
## 2   2017-01-03     753.67      62.58     116.15     216.99  0.005067529
## 3   2017-01-04     757.18      62.30     116.02     226.99  0.004657224
## 125 2017-06-29     975.93      68.49     143.68     360.75 -0.014540632
##         MSFT.ret     AAPL.ret    TSLA.ret
## 1             NA           NA          NA
## 2    0.007080902  0.002849238  0.01544295
## 3   -0.004474330 -0.001119264  0.04608507
## 125 -0.018767921 -0.014743251 -0.02825663

Step 2: Convert Net Returns to Gross Returns

vwport$AMZN.ret <- vwport$AMZN.ret + 1
vwport$MSFT.ret <- vwport$MSFT.ret + 1
vwport$AAPL.ret <- vwport$AAPL.ret + 1
vwport$TSLA.ret <- vwport$TSLA.ret + 1
vwport[c(1:3, nrow(vwport)), ]
##           date AMZN.Close MSFT.Close AAPL.Close TSLA.Close  AMZN.ret
## 1   2016-12-30     749.87      62.14     115.82     213.69        NA
## 2   2017-01-03     753.67      62.58     116.15     216.99 1.0050675
## 3   2017-01-04     757.18      62.30     116.02     226.99 1.0046572
## 125 2017-06-29     975.93      68.49     143.68     360.75 0.9854594
##      MSFT.ret  AAPL.ret  TSLA.ret
## 1          NA        NA        NA
## 2   1.0070809 1.0028492 1.0154429
## 3   0.9955257 0.9988807 1.0460851
## 125 0.9812321 0.9852567 0.9717434

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

# Construct Series of Calendar Days
date <- seq(as.Date("2016-12-31"), as.Date("2017-12-31"), by = 1)
date <- data.frame(date)
date[c(1:3, nrow(date)), ]
## [1] "2016-12-31" "2017-01-01" "2017-01-02" "2017-12-31"

# Create Data Object with Daily Prices
PRICE.qtr <- vwport[, 1:5]
PRICE.qtr[c(1:3, nrow(PRICE.qtr)), ]
##           date AMZN.Close MSFT.Close AAPL.Close TSLA.Close
## 1   2016-12-30     749.87      62.14     115.82     213.69
## 2   2017-01-03     753.67      62.58     116.15     216.99
## 3   2017-01-04     757.18      62.30     116.02     226.99
## 125 2017-06-29     975.93      68.49     143.68     360.75

# 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 MSFT.Close AAPL.Close TSLA.Close
## 1   2016-12-31       <NA>       <NA>       <NA>       <NA>
## 2   2017-01-01       <NA>       <NA>       <NA>       <NA>
## 3   2017-01-02       <NA>       <NA>       <NA>       <NA>
## 366 2017-12-31     975.93      68.49     143.68     360.75

# Keep Only Prices at the End of Each Calendar Quarter
PRICE.qtr <- subset(PRICE.qtr,
                    PRICE.qtr$date == as.Date("2016-12-31") |
                    PRICE.qtr$date == as.Date("2017-06-30"))
PRICE.qtr
##           date AMZN.Close MSFT.Close AAPL.Close TSLA.Close
## 1   2016-12-31       <NA>       <NA>       <NA>       <NA>
## 182 2017-06-30     975.93      68.49     143.68     360.75

# 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(477000000, 478000000)
PRICE.qtr$MSFT.shout <- c(7808000000, 7723000000)
PRICE.qtr$AAPL.shout <- c(5336166000, 5205815000)
PRICE.qtr$TSLA.shout <- c(161561000, 164164000)
PRICE.qtr
##           date AMZN.Close MSFT.Close AAPL.Close TSLA.Close AMZN.shout
## 1   2016-12-31       <NA>       <NA>       <NA>       <NA>   4.77e+08
## 182 2017-06-30     975.93      68.49     143.68     360.75   4.78e+08
##     MSFT.shout AAPL.shout TSLA.shout
## 1    7.808e+09 5336166000  161561000
## 182  7.723e+09 5205815000  164164000

# Calculate Market Capitalization of Each Security
str(PRICE.qtr)
## 'data.frame':    2 obs. of  9 variables:
##  $ date      : chr  "2016-12-31" "2017-06-30"
##  $ AMZN.Close: chr  NA " 975.93"
##  $ MSFT.Close: chr  NA "68.49"
##  $ AAPL.Close: chr  NA "143.68"
##  $ TSLA.Close: chr  NA "360.75"
##  $ AMZN.shout: num  4.77e+08 4.78e+08
##  $ MSFT.shout: num  7.81e+09 7.72e+09
##  $ AAPL.shout: num  5.34e+09 5.21e+09
##  $ TSLA.shout: num  1.62e+08 1.64e+08
PRICE.qtr$date <- as.Date(PRICE.qtr$date)
PRICE.qtr$AMZN.Close <- as.numeric(PRICE.qtr$AMZN.Close)
PRICE.qtr$MSFT.Close <- as.numeric(PRICE.qtr$MSFT.Close)
PRICE.qtr$AAPL.Close <- as.numeric(PRICE.qtr$AAPL.Close)
PRICE.qtr$TSLA.Close <- as.numeric(PRICE.qtr$TSLA.Close)
str(PRICE.qtr)
## 'data.frame':    2 obs. of  9 variables:
##  $ date      : Date, format: "2016-12-31" "2017-06-30"
##  $ AMZN.Close: num  NA 976
##  $ MSFT.Close: num  NA 68.5
##  $ AAPL.Close: num  NA 144
##  $ TSLA.Close: num  NA 361
##  $ AMZN.shout: num  4.77e+08 4.78e+08
##  $ MSFT.shout: num  7.81e+09 7.72e+09
##  $ AAPL.shout: num  5.34e+09 5.21e+09
##  $ TSLA.shout: num  1.62e+08 1.64e+08

weights <- PRICE.qtr
weights$AMZN.mcap <- weights$AMZN.Close * weights$AMZN.shout
weights$MSFT.mcap <- weights$MSFT.Close * weights$MSFT.shout
weights$AAPL.mcap <- weights$AAPL.Close * weights$AAPL.shout
weights$TSLA.mcap <- weights$TSLA.Close * weights$TSLA.shout
weights
##           date AMZN.Close MSFT.Close AAPL.Close TSLA.Close AMZN.shout
## 1   2016-12-31         NA         NA         NA         NA   4.77e+08
## 182 2017-06-30     975.93      68.49     143.68     360.75   4.78e+08
##     MSFT.shout AAPL.shout TSLA.shout    AMZN.mcap    MSFT.mcap
## 1    7.808e+09 5336166000  161561000           NA           NA
## 182  7.723e+09 5205815000  164164000 466494540000 528948270000
##        AAPL.mcap   TSLA.mcap
## 1             NA          NA
## 182 747971499200 59222163000

# Calculate Quarter-end Aggregate Market Capitalization
weights$tot.mcap <- rowSums(weights[, 10:13])
weights
##           date AMZN.Close MSFT.Close AAPL.Close TSLA.Close AMZN.shout
## 1   2016-12-31         NA         NA         NA         NA   4.77e+08
## 182 2017-06-30     975.93      68.49     143.68     360.75   4.78e+08
##     MSFT.shout AAPL.shout TSLA.shout    AMZN.mcap    MSFT.mcap
## 1    7.808e+09 5336166000  161561000           NA           NA
## 182  7.723e+09 5205815000  164164000 466494540000 528948270000
##        AAPL.mcap   TSLA.mcap     tot.mcap
## 1             NA          NA           NA
## 182 747971499200 59222163000 1.802636e+12

Step 4: Calculate Quarter-end Weights of Each Security in the Portfolio

weights$AMZN.wgt <- weights$AMZN.mcap / weights$tot.mcap
weights$MSFT.wgt <- weights$MSFT.mcap / weights$tot.mcap
weights$AAPL.wgt <- weights$AAPL.mcap / weights$tot.mcap
weights$TSLA.wgt <- weights$TSLA.mcap / weights$tot.mcap
weights
##           date AMZN.Close MSFT.Close AAPL.Close TSLA.Close AMZN.shout
## 1   2016-12-31         NA         NA         NA         NA   4.77e+08
## 182 2017-06-30     975.93      68.49     143.68     360.75   4.78e+08
##     MSFT.shout AAPL.shout TSLA.shout    AMZN.mcap    MSFT.mcap
## 1    7.808e+09 5336166000  161561000           NA           NA
## 182  7.723e+09 5205815000  164164000 466494540000 528948270000
##        AAPL.mcap   TSLA.mcap     tot.mcap  AMZN.wgt  MSFT.wgt AAPL.wgt
## 1             NA          NA           NA        NA        NA       NA
## 182 747971499200 59222163000 1.802636e+12 0.2587846 0.2934304 0.414932
##       TSLA.wgt
## 1           NA
## 182 0.03285308

weights <- weights[, c(1, 10:18)]
weights
##           date    AMZN.mcap    MSFT.mcap    AAPL.mcap   TSLA.mcap
## 1   2016-12-31           NA           NA           NA          NA
## 182 2017-06-30 466494540000 528948270000 747971499200 59222163000
##         tot.mcap  AMZN.wgt  MSFT.wgt AAPL.wgt   TSLA.wgt
## 1             NA        NA        NA       NA         NA
## 182 1.802636e+12 0.2587846 0.2934304 0.414932 0.03285308

weights$date <- weights$date + 1 #since the weights are applicable at the start of the next Q
weights
##           date    AMZN.mcap    MSFT.mcap    AAPL.mcap   TSLA.mcap
## 1   2017-01-01           NA           NA           NA          NA
## 182 2017-07-01 466494540000 528948270000 747971499200 59222163000
##         tot.mcap  AMZN.wgt  MSFT.wgt AAPL.wgt   TSLA.wgt
## 1             NA        NA        NA       NA         NA
## 182 1.802636e+12 0.2587846 0.2934304 0.414932 0.03285308

Step 5: Calculate the Quarterly VW Portfolio Values

q1.vw.wgt <- subset(weights, date == "2017-12-30") #I'm not sure why author took the long way
q2.vw.wgt <- subset(weights, date == "2017-06-29")
q1.vw.wgt
##  [1] date      AMZN.mcap MSFT.mcap AAPL.mcap TSLA.mcap tot.mcap  AMZN.wgt 
##  [8] MSFT.wgt  AAPL.wgt  TSLA.wgt 
## <0 rows> (or 0-length row.names)
q2.vw.wgt
##  [1] date      AMZN.mcap MSFT.mcap AAPL.mcap TSLA.mcap tot.mcap  AMZN.wgt 
##  [8] MSFT.wgt  AAPL.wgt  TSLA.wgt 
## <0 rows> (or 0-length row.names)

Step 7: Calculate VW Portfolio Values for 1Q 2013

vw.q1 <- subset(vwport,
                vwport$date >= as.Date("2016-12-30") &
                vwport$date <= as.Date("2017-06-29"))
vw.q1[c(1:3, nrow(vw.q1)), ]
##           date AMZN.Close MSFT.Close AAPL.Close TSLA.Close  AMZN.ret
## 1   2016-12-30     749.87      62.14     115.82     213.69        NA
## 2   2017-01-03     753.67      62.58     116.15     216.99 1.0050675
## 3   2017-01-04     757.18      62.30     116.02     226.99 1.0046572
## 125 2017-06-29     975.93      68.49     143.68     360.75 0.9854594
##      MSFT.ret  AAPL.ret  TSLA.ret
## 1          NA        NA        NA
## 2   1.0070809 1.0028492 1.0154429
## 3   0.9955257 0.9988807 1.0460851
## 125 0.9812321 0.9852567 0.9717434

vw.q1 <- vw.q1[, c(1, 6:9)]
vw.q1[c(1:3, nrow(vw.q1)), ]
##           date  AMZN.ret  MSFT.ret  AAPL.ret  TSLA.ret
## 1   2016-12-30        NA        NA        NA        NA
## 2   2017-01-03 1.0050675 1.0070809 1.0028492 1.0154429
## 3   2017-01-04 1.0046572 0.9955257 0.9988807 1.0460851
## 125 2017-06-29 0.9854594 0.9812321 0.9852567 0.9717434

names(vw.q1)[2:5] <- paste(c("AMZN", "MSFT", "AAPL", "TSLA"))
vw.q1[c(1:3, nrow(vw.q1)), ]
##           date      AMZN      MSFT      AAPL      TSLA
## 1   2016-12-30        NA        NA        NA        NA
## 2   2017-01-03 1.0050675 1.0070809 1.0028492 1.0154429
## 3   2017-01-04 1.0046572 0.9955257 0.9988807 1.0460851
## 125 2017-06-29 0.9854594 0.9812321 0.9852567 0.9717434

vw.q1[1, 2:5] <- 1
vw.q1$AMZN <- cumprod(vw.q1$AMZN) 
vw.q1$MSFT <- cumprod(vw.q1$MSFT)
vw.q1$AAPL <- cumprod(vw.q1$AAPL)
vw.q1$TSLA <- cumprod(vw.q1$TSLA)
vw.q1[c(1:3, nrow(vw.q1)), ]
##           date     AMZN     MSFT     AAPL     TSLA
## 1   2016-12-30 1.000000 1.000000 1.000000 1.000000
## 2   2017-01-03 1.005068 1.007081 1.002849 1.015443
## 3   2017-01-04 1.009748 1.002575 1.001727 1.062240
## 125 2017-06-29 1.301466 1.115227 1.251067 1.688193