Reputation: 37
I have tried to set up a R-code to calculate returns of each column. My problem is that the code should consider multiple investments of different time periods in each asset (column).
I have managed to extract the relevant prices of each day in which each investment was owned (rows) as an xts-object. NAs indicate that a given stock was not owned on the given date. Therefore, I have a table as shown below (as a xts object). Also, please note that the weekend is not included in the index column:
Stock 1 Stock 2 Stock 3 Stock 4 Stock 4
2019-10-18 100 NA NA 750 NA
2019-10-21 105 NA NA 1000 6
2019-10-22 110 NA NA NA 7
2019-10-23 NA NA NA 750 8
2019-10-24 10 NA NA 500 8
2019-10-25 7.5 NA NA NA 8
2019-10-28 5 NA NA 500 8
2019-10-29 NA NA 200 250 9
To interpret the table an example follows: Stock 1 was owned in the period from 2019-10-18 to 2019-10-22 where it was sold. On 2019-10-23 Stock 1 was not owned, whereas it was bought again on 2019-10-24 and sold again on 2019-10-28, and therefore a NA on 2019-10-29. The numbers in the column of Stock 1 reflect the stock prices for the given days.
The output I search to obtain is a vector summarizing each independent investment - which is not based upon the investment size:
Stock 1 Stock 2 Stock 3 Stock 4 Stock 5
Cumulative Return -40% NA 0% -50% 50%
Notice that each investment make use of the first and last row of each investment period to calculate the cumulative return. As an example -40% is calculated as: 110/100-1 + 5/10-1
.
If multiple investments are made in an asset (column), it will always be of non-overlapping periods as in the example above.
Thanks in advance!
Upvotes: 1
Views: 708
Reputation: 1493
The number you want to compute is similar to what is (unfortunately) called time-weighted returns; though for such returns, the single-trade returns are chained together via multiplication, not via summing. In fact, if that would be acceptable, it is quite easy to compute. Start with data:
library("PMwR")
library("zoo")
data <- structure(
c(100, 105, 110, NA, 10, 7.5, 5, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, 200, 750, 1000, NA, 750, 500, NA, 500,
250, NA, 6, 7, 8, 8, 8, 8, 9),
.Dim = c(8L, 5L),
.Dimnames = list(NULL, c("Stock1", "Stock2", "Stock3",
"Stock4", "Stock5")),
index = structure(c(18187, 18190, 18191, 18192, 18193,
18194, 18197, 18198), class = "Date"),
class = "zoo")
data
## Stock1 Stock2 Stock3 Stock4 Stock5
## 2019-10-18 100.0 NA NA 750 NA
## 2019-10-21 105.0 NA NA 1000 6
## 2019-10-22 110.0 NA NA NA 7
## 2019-10-23 NA NA NA 750 8
## 2019-10-24 10.0 NA NA 500 8
## 2019-10-25 7.5 NA NA NA 8
## 2019-10-28 5.0 NA NA 500 8
## 2019-10-29 NA NA 200 250 9
Note that I use zoo
here, but you can always call as.xts
(as xts
inherits from zoo
). From PMwR
I use function returns
. For time-weighted returns (i.e. the product of single-trade returns), simply transform all NA-returns into zeros.
R <- returns(data, pad = 0)
R <- na.fill(R, 0)
apply(R, 2, function(x) prod(1+x)-1)
## Stock1 Stock2 Stock3 Stock4 Stock5
## -0.4500000 0.0000000 0.0000000 -0.5555556 0.5000000
If you really want to sums of the returns, there is slightly more work to do:
sum_returns <- function(x) {
x <- c(NA, as.vector(x), NA)
start <- which(is.finite(x[-1]) & is.na (x[-length(x)]))
end <- which(is.na (x[-1]) & is.finite(x[-length(x)]))
sum(x[end]/x[start+1]-1)
}
apply(data, 2, sum_returns)
## Stock1 Stock2 Stock3 Stock4 Stock5
## -0.4 0.0 0.0 -0.5 0.5
If you need to differentiate between zero return and never invested, add something like
never.invested <- apply(data, 2, function(x) all(is.na(x)))
## Stock1 Stock2 Stock3 Stock4 Stock5
## FALSE TRUE FALSE FALSE FALSE
Upvotes: 1