# R - Portfolio construction based on own calculations, with rebalancing of components

I have used random forest in R to get probabilities for stocks being in a certain class. With those probabilities i would like to construct portfolios containing the 5 stocks with the highest probabilities on the first date of the dataset, and then rebalance this every 10 days with the stocks with the highest ranking at that time. The portfolio should be equal weighted.

Here is some example data that i think is representable of my data.

Date <- rep(seq(as.Date("2009/01/01"), by = "day", length.out = 100), 10)
Name <- c(rep("Stock A", 100), rep("Stock B",100), rep("Stock C", 100), rep("Stock D", 100), rep("Stock E",100), rep("Stock F",100), rep("Stock G",100), rep("Stock H",100), rep("Stock I", 100), rep("Stock J", 100))
Return <- rnorm(1000)
Prob <- runif(1000)

DF <- data.frame(Date, Name, Return, Prob)
DF <- DF %>% arrange(Date, desc(Prob))

> head(DF)
Date    Name      Return      Prob
1 2009-01-01 Stock F  0.52259644 0.8084277
2 2009-01-01 Stock A  0.57720376 0.7617348
3 2009-01-01 Stock B -0.09864981 0.7256358
4 2009-01-01 Stock E -1.26136381 0.6200346
5 2009-01-01 Stock G -1.37360527 0.5680765
6 2009-01-01 Stock D -0.04794049 0.4793370


So the portfolio would contain stock F, A, B, E, and G for the first 10 days, and then rebalance it with the stocks of the highest percentage.

I am not very good at coding and R, and have tried looking at options as to how i can do this with PortfolioAnalytics, PerformanceAnalytics and tidyquant, but am not able to find a solution where i understand how to do this, as i am not interested in using any form of optimizing. I need a simple portfolio determined by my calculated percentages, with rebalancing.

If anyone has any suggestions as to how i can do this, i would highly appreciate it. And if this is the wrong forum for posting this question, i am sorry and will post it elsewhere.

Using dplyr::group_by and dplyr::top_n to get the highest probabilities by date. Then expand to get a weight vector. See my comments in the code.

library(dplyr)

weights <- DF %>%
# filter the dates you want to rebalance on
filter(Date %in% seq(min(Date), max(Date), by = "10 days")) %>%
# group by Date and get the top 5 by Prob
group_by(Date) %>%
top_n(5, Prob) %>%
# ungroup removes the grouping again
ungroup() %>%
# select Date and Name and add the weight
select(Date, Name) %>%
mutate(weight = 1/5) %>%
# last step is to complete the weights over all dates
# (I transform it to wide format first, and locf "last observation carried forward" the NAs,
#  there might be a more elegant way for this, I'm not sure)
pivot_wider(names_from = "Name", values_from = "weight", values_fill = list(weight = 0)) %>%
complete(Date = seq(as.Date("2009/01/01"), by = "day", length.out = 100)) %>%
mutate_at(vars(starts_with("Stock")), na.locf) %>%
pivot_longer(names_to = "Name", values_to = "weight", -"Date")

DF %>%
# join the weights to the original returns
left_join(weights, by = c("Date", "Name")) %>%
# calculate PF Returns
group_by(Date) %>%
summarise(Return = sum(Return*weight))
$$$$
`
• Thank you so much for this! It looks to be what i needed, i will try it tomorrow. Commented Apr 16, 2020 at 20:03