I know there are good resources for calculating stock and portfolio returns using performance analytics in tidyquant for R. For example, assume we want to determine the annual portfolio returns (2011 through 2015) for a portfolio that contains "XOM" (0.5), "MA" (0.3), and "GOOG" (0.2), where () indicates the asset weight within the portfolio. The code would simply be:
Ra_symbols <- c("XOM", "MA", "GOOG")
wts_map <- tibble(
symbols = c("XOM", "MA", "GOOG"),
weights = c(0.5, 0.3, 0.2)
)
Ra_2010to2020 <- Ra_symbols %>%
tq_get(get = "stock.prices",
from = "2010-12-31",
to = "2015-12-31") %>%
group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = "yearly",
col_rename = "Ra")
Ra_weightedportfolioreturn <- Ra_2010to2020 %>%
tq_portfolio(assets_col = symbol,
returns_col = Ra,
weights = wts_map,
col_rename = "Ra_using_wts_map")
But I cannot find any resource to help with the code if the portfolio contains different assets in each year with varying weights. For example, assume we have two dataframes: one with the symbols for each year and one with the respective portfolio weights. Below is the code to read in the csv file with the symbols and weights, along with images to illustrate the dataframes.
symbols2011to2015 <- read_csv("Symboltest_2011to2015.csv")
weights2011to2015 <- read_csv("wtstest_2011to2015.csv")
I'm thinking it's going to involve some tidyverse functions like "apply" or "map", but am not sure. Also, can tidyquant work with symbols (and weights) in a dataframe as I have it, or do I need to convert them to character values similar to the results from c("XOM", "MA", "GOOG")? Eventually, I'd like to expand this concept for monthly periods, but once I figure it out for multiple years the process should be similar.
Any help would be much appreciated!
(This is a follow up to the comment.)
There is documentation in the PMwR
manual.
The input to returns
does not have to be a zoo
series: matrices or data-frames will work as well, as long as the prices are arranged in columns. However, working with zoo
is quite convenient. To take your example:
library("zoo")
library("tidyquant")
P <- tq_get(c("XOM", "MA", "GOOG"),
get = "stock.prices",
from = "2010-12-31",
to = "2015-12-31")
P <- do.call(merge, by(P, P$symbol, function(x) zoo(x$adjusted, x$date)))
## GOOG MA XOM
## 2010-12-31 295.8760 21.09419 50.33540
## 2011-01-03 301.0466 20.78734 51.31982
## 2011-01-04 299.9358 21.05560 51.56077
## 2011-01-05 303.3978 21.67588 51.42308
## 2011-01-06 305.6045 21.76818 51.75351
## 2011-01-07 307.0690 21.76536 52.03575
Now suppose you have a matrix W
of weights
W <- rbind(c(1/3, 1/3, 1/3),
c(0.6, 0.2, 0.2),
c(1/3, 1/3, 1/3),
c(0.6, 0.2, 0.2),
c(1/3, 1/3, 1/3))
and dates when to rebalance:
when <- as.Date(c("2010-12-31", "2011-12-30", "2012-12-31",
"2013-12-31", "2014-12-31"))
Each element in when
corresponds to a row in W
.
Now we can compute portfolio returns.
library("PMwR")
R <- returns(P, rebalance.when = when, weights = W)
## 2011-01-03 2011-01-04 2011-01-05 2011-01-06 ....
## 0.007495421 0.004549025 0.012637607 0.005984054 ....
## ## If 'P' had not been a zoo matrix:
## returns(coredata(P), t = index(P), rebalance.when = when, weights = W)
## ## would work as well
returns
expects as input a price series. We can easily create such a series, based on R
.
tmp <- cumprod(1 + returns(P, rebalance.when = when, weights = W, pad = 0))
This series we can transform into holding-period returns.
returns(tmp, period = "month")
## Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec YTD
## 2011 5.7 3.5 -0.4 2.7 -0.9 -0.1 4.5 -1.7 -3.5 10.4 4.8 3.4 31.4
## 2012 -7.3 8.4 2.2 -1.7 -6.3 3.0 5.7 4.2 8.4 -5.4 2.3 0.5 13.2
## 2013 5.5 2.1 1.4 1.7 3.8 0.6 3.6 -3.8 4.7 9.7 4.6 7.9 49.7
## 2014 -0.4 3.3 -5.7 -2.6 4.3 1.0 -0.6 0.6 -0.9 1.0 -2.1 -1.6 -4.0
## 2015 -2.8 5.5 -3.3 1.8 -0.1 -1.0 6.8 -3.4 -1.8 13.0 1.3 0.7 16.6
returns(tmp, period = "year")
## 2011 2012 2013 2014 2015
## 31.4 13.2 49.7 -4.0 16.6