Total Return and Price Return
quantmod and xts packageslibrary(quantmod)
## Loading required package: xts
## Loading required package: zoo
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
## Loading required package: TTR
## Version 0.4-0 included new data defaults. See ?getSymbols.
library(xts)
data.IBM <- read.csv("IBM Yahoo.csv", header=TRUE)
date <- as.Date(data.IBM$Date,format="%Y-%m-%d")
data.IBM <- cbind(date,data.IBM[,-1])
data.IBM <- data.IBM[order(data.IBM$date),]
data.IBM <- xts(data.IBM[,2:7],order.by=data.IBM[,1])
names(data.IBM) <-
paste(c("IBM.Open","IBM.High","IBM.Low",
"IBM.Close","IBM.Volume","IBM.Adjusted"))
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
data.IBM, this is IBM.Close or column 4. Subset the data to only include IBM closing priceIBM.prc.ret <- data.IBM[,4]
IBM.prc.ret[c(1:3,nrow(IBM.prc.ret))]
## IBM.Close
## 2010-12-31 146.76
## 2011-01-03 147.48
## 2011-01-04 147.64
## 2013-12-31 187.57
IBM.prc.ret$IBM.prc.ret <- Delt(IBM.prc.ret$IBM.Close)
IBM.prc.ret[c(1:3,nrow(IBM.prc.ret)),]
## IBM.Close IBM.prc.ret
## 2010-12-31 146.76 NA
## 2011-01-03 147.48 0.004905976
## 2011-01-04 147.64 0.001084913
## 2013-12-31 187.57 0.006222858
Since the first observation is NA, we can delete this observation in IBM.prc.ret
Since we are dealing with returns, we do not need IBM.Clsoe and the first column can also be deleted
options(digits=3)
IBM.prc.ret <- IBM.prc.ret[-1,2]
IBM.prc.ret[c(1:3,nrow(IBM.prc.ret)),]
## IBM.prc.ret
## 2011-01-03 0.00491
## 2011-01-04 0.00108
## 2011-01-05 -0.00400
## 2013-12-31 0.00622
options(digits=7)
The return to investors from holding shares of stock are not liited to changes in the price of the security (there are also dividends)
Total return equals the sum of both the change in price of the shares and any income generated from the dividends and the reinvestment of those dividends
For a daily total return calculation, the dividend yield is zero or non-ex dividend dates
Yahoo Finance gives us an adjusted closing prie varialbe, which in data.IBM, is the 6th column (labeled IBM.Adjusted)
We will now calculate IBM’s total returns from January 2011 to December 2013
data.IBM[715:720,]
## IBM.Open IBM.High IBM.Low IBM.Close IBM.Volume IBM.Adjusted
## 2013-11-01 179.81 180.34 178.88 179.23 3644500 161.0826
## 2013-11-04 179.90 180.80 179.34 180.27 3483300 162.0173
## 2013-11-05 179.54 179.80 177.71 177.85 6096800 159.8423
## 2013-11-06 177.91 179.75 177.78 179.19 4560700 161.9115
## 2013-11-07 179.60 181.39 179.60 180.00 5219500 162.6434
## 2013-11-08 178.83 180.08 177.35 179.99 6275000 162.6344
IBM.data, we only need to check that t is still in the R memory. If it is, keep the adjusted close price or column 6 in data.IBMIBM.ret <- data.IBM[,6]
IBM.ret[c(1:3,nrow(IBM.ret)),]
## IBM.Adjusted
## 2010-12-31 125.8031
## 2011-01-03 126.4203
## 2011-01-04 126.5574
## 2013-12-31 169.4835
When we apply the Delt command on the adjusted close price we calcualte the total return
Total return equals price return on non ex-dividend days and the total return is higher than the price return on ex-dividend days
IBM.ret$IBM.tot.ret=Delt(IBM.ret$IBM.Adjusted)
IBM.ret[c(1:3,nrow(IBM.ret)),]
## IBM.Adjusted IBM.tot.ret
## 2010-12-31 125.8031 NA
## 2011-01-03 126.4203 0.004905977
## 2011-01-04 126.5574 0.001084913
## 2013-12-31 169.4835 0.006222858
digits=3 optionoptions(digits=3)
IBM.ret <- IBM.ret[,2]
IBM.ret[c(1:3,nrow(IBM.ret)),]
## IBM.tot.ret
## 2010-12-31 NA
## 2011-01-03 0.00491
## 2011-01-04 0.00108
## 2013-12-31 0.00622
options(digits=7)
The returns using the Delt command are called arithmetic returns, or simple returns
Logartithmic returns are used a lot in various areas of finance
Calculate the logarithmic total return for IBM stock from January 2011 to December 2013
IBM.log.ret <- data.IBM[,6]
IBM.log.ret[c(1:3,nrow(IBM.log.ret)),]
## IBM.Adjusted
## 2010-12-31 125.8031
## 2011-01-03 126.4203
## 2011-01-04 126.5574
## 2013-12-31 169.4835
diff and log commands to calculate logarithmic returnsIBM.log.ret$IBM.log.ret <- diff(log(IBM.log.ret$IBM.Adjusted))
IBM.log.ret[c(1:3,nrow(IBM.log.ret)),]
## IBM.Adjusted IBM.log.ret
## 2010-12-31 125.8031 NA
## 2011-01-03 126.4203 0.004893982
## 2011-01-04 126.5574 0.001084325
## 2013-12-31 169.4835 0.006203576
IBM.log.ret to delete the first coumn and keep only the logarithmic return seriesoptions(digits=3)
IBM.log.ret <- IBM.log.ret[,2]
IBM.log.ret[c(1:3,nrow(IBM.log.ret)),]
## IBM.log.ret
## 2010-12-31 NA
## 2011-01-03 0.00489
## 2011-01-04 0.00108
## 2013-12-31 0.00620
options(digits=7)
Compare Log Returns with Artihmetic Returns
Combine the two total return calculations using the cbind command
Use the na.rm=TRUE option so that R still calculates a max and a min even though there is an NA in the data
options(digits=3,scipen=100)
tot.rets <- cbind(IBM.ret,IBM.log.ret)
tot.rets[c(1:3,nrow(tot.rets)),]
## IBM.tot.ret IBM.log.ret
## 2010-12-31 NA NA
## 2011-01-03 0.00491 0.00489
## 2011-01-04 0.00108 0.00108
## 2013-12-31 0.00622 0.00620
max(abs(tot.rets$IBM.tot.ret-tot.rets$IBM.log.ret),na.rm=TRUE)
## [1] 0.00363
min(abs(tot.rets$IBM.tot.ret-tot.rets$IBM.log.ret),na.rm=TRUE)
## [1] 0.00000000118
options(digits=7,scipen=0)
We used scipen=100 to increase the threshold before R converts the output into scientific notation
Once done, revert the scipen option back to zero so that the output of subsequent analyses will revert back to the default display options
To fully capture the effects of being able to reinvest dividends, we should calculate daily returns and string them together for longer periods
The returns of that stock going forward determines whether the reinvested dividend earned a positive or negative return
To string together multiple days of arithmetic returns, we have to take the product of the daily gross returns
IBM.ret to see that we have the correct data still available in R memoryIBM.acum <- IBM.ret
IBM.acum[c(1:3,nrow(IBM.acum)),]
## IBM.tot.ret
## 2010-12-31 NA
## 2011-01-03 0.004905977
## 2011-01-04 0.001084913
## 2013-12-31 0.006222858
IBM.acum[1,1]<-0
IBM.acum[c(1:3,nrow(IBM.acum)),]
## IBM.tot.ret
## 2010-12-31 0.000000000
## 2011-01-03 0.004905977
## 2011-01-04 0.001084913
## 2013-12-31 0.006222858
IBM.acum$GrossRet <- 1+IBM.acum$IBM.tot.ret
IBM.acum[c(1:3,nrow(IBM.acum)),]
## IBM.tot.ret GrossRet
## 2010-12-31 0.000000000 1.000000
## 2011-01-03 0.004905977 1.004906
## 2011-01-04 0.001084913 1.001085
## 2013-12-31 0.006222858 1.006223
Use the cumprod command to take the cumulative product of the gross return
cumprod takes the product of all the gross returns
IBM.acum$GrossCum <- cumprod(IBM.acum$GrossRet)
IBM.acum[c(1:3,nrow(IBM.acum)),]
## IBM.tot.ret GrossRet GrossCum
## 2010-12-31 0.000000000 1.000000 1.000000
## 2011-01-03 0.004905977 1.004906 1.004906
## 2011-01-04 0.001084913 1.001085 1.005996
## 2013-12-31 0.006222858 1.006223 1.347213
Subtract one from the GrossCum to calculate the net cumulative return or NetCum
NetCum is interpreted as the percentage return from the investment date
IBM.acum$NetCum <- IBM.acum$GrossCum-1
IBM.acum[c(1:3,nrow(IBM.acum)),]
## IBM.tot.ret GrossRet GrossCum NetCum
## 2010-12-31 0.000000000 1.000000 1.000000 0.000000000
## 2011-01-03 0.004905977 1.004906 1.004906 0.004905977
## 2011-01-04 0.001084913 1.001085 1.005996 0.005996213
## 2013-12-31 0.006222858 1.006223 1.347213 0.347212558
IBM.logret to see that we have the correct data still available in the R memoryIBM.logcum <- IBM.log.ret
IBM.logcum[c(1:3,nrow(IBM.logcum)),]
## IBM.log.ret
## 2010-12-31 NA
## 2011-01-03 0.004893982
## 2011-01-04 0.001084325
## 2013-12-31 0.006203576
IBM.logcum[1,1]<-0
IBM.logcum[c(1:3,nrow(IBM.logcum)),]
## IBM.log.ret
## 2010-12-31 0.000000000
## 2011-01-03 0.004893982
## 2011-01-04 0.001084325
## 2013-12-31 0.006203576
Sum command, add up the values in IBM.log.retlogcumret=sum(IBM.logcum$IBM.log.ret)
logcumret
## [1] 0.2980377
exp command (exponential logarithmic)cumret=exp(logcumret)-1
cumret
## [1] 0.3472126
We have already combined the price and total returns data from tot.rets, so we only need to call in data
Rename the data to better identify the variables as prc.ret and tot.ret
IBM.Ret <- cbind(IBM.prc.ret,IBM.ret)
names(IBM.Ret) <- c("prc.ret","tot.ret")
IBM.Ret[c(1:3,nrow(IBM.Ret)),]
## prc.ret tot.ret
## 2010-12-31 NA NA
## 2011-01-03 0.004905976 0.004905977
## 2011-01-04 0.001084913 0.001084913
## 2013-12-31 0.006222858 0.006222858
IBM.Ret$prc.ret[1] <- 0
IBM.Ret$tot.ret[1] <- 0
IBM.Ret[c(1:3,nrow(IBM.Ret)),]
## prc.ret tot.ret
## 2010-12-31 0.000000000 0.000000000
## 2011-01-03 0.004905976 0.004905977
## 2011-01-04 0.001084913 0.001084913
## 2013-12-31 0.006222858 0.006222858
gross.prc and gross total return gross.totIBM.Ret$gross.prc<-1+IBM.Ret$prc.ret
IBM.Ret$gross.tot<-1+IBM.Ret$tot.ret
IBM.Ret[c(1:3,nrow(IBM.Ret)),]
## prc.ret tot.ret gross.prc gross.tot
## 2010-12-31 0.000000000 0.000000000 1.000000 1.000000
## 2011-01-03 0.004905976 0.004905977 1.004906 1.004906
## 2011-01-04 0.001084913 0.001084913 1.001085 1.001085
## 2013-12-31 0.006222858 0.006222858 1.006223 1.006223
cum.prc and cumulative total return cum.tot by using the cumprod commandIBM.Ret$cum.prc <- cumprod(IBM.Ret$gross.prc)
IBM.Ret$cum.tot <- cumprod(IBM.Ret$gross.tot)
IBM.Ret[c(1:3,nrow(IBM.Ret)),]
## prc.ret tot.ret gross.prc gross.tot cum.prc cum.tot
## 2010-12-31 0.000000000 0.000000000 1.000000 1.000000 1.000000 1.000000
## 2011-01-03 0.004905976 0.004905977 1.004906 1.004906 1.004906 1.004906
## 2011-01-04 0.001084913 0.001084913 1.001085 1.001085 1.005996 1.005996
## 2013-12-31 0.006222858 0.006222858 1.006223 1.006223 1.278073 1.347213
First plot the cum.tot variable, and then plot the cum.prc variable
Using the abline command, add a horizontal line at $1 so we can interpret whether the investment is making money or losing money
y.range <- range(IBM.Ret[,5:6])
y.range
## [1] 1.000000 1.526869
plot(IBM.Ret$cum.tot,
type="l",
auto.grid=FALSE,
xlab="Date",
ylab="Value of Investment ($)",
ylim=y.range,
minor.ticks=FALSE,
main="IBM Stock Performance Based on
Total Returns and Price Returns
December 31, 2010 - December 31, 2013")
lines(IBM.Ret$cum.prc,
type="l",
lty=3)
abline(h=1,col="black")
legend("topleft",
col=c("black","black"),
lty=c(1,3),
c("Value Based on Total Return",
"Value Based on Price Return"))