# Load packages

# Core
library(tidyverse)
library(tidyquant)

Goal

Collect individual returns into a portfolio by assigning a weight to each stock Choose your stocks.

1 Import stock prices

symbols <- c("BRK-B", "NVDA", "LLY", "XPEV", "RTX", "CVLG", "JNJ", "JPM")

prices <- tq_get(x    = symbols, 
                 get  = "stock.prices", 
                 from = "2020-04-01",
                 to   = "2025-05-20")
prices
## # A tibble: 10,217 × 8
##    symbol date        open  high   low close   volume adjusted
##    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
##  1 BRK-B  2020-04-01  176.  179.  174.  176.  8682700     176.
##  2 BRK-B  2020-04-02  175   180.  174.  180.  7271900     180.
##  3 BRK-B  2020-04-03  179.  180.  175.  178.  6643700     178.
##  4 BRK-B  2020-04-06  185.  186.  180.  185.  9935500     185.
##  5 BRK-B  2020-04-07  192.  192   185.  185.  8148200     185.
##  6 BRK-B  2020-04-08  188.  191.  185.  191.  6109900     191.
##  7 BRK-B  2020-04-09  194   197.  191.  194. 10519600     194.
##  8 BRK-B  2020-04-13  194.  194.  186.  189.  7888600     189.
##  9 BRK-B  2020-04-14  193.  194.  191.  193.  7032000     193.
## 10 BRK-B  2020-04-15  189.  190.  187.  189.  6138300     189.
## # ℹ 10,207 more rows

2 Prices to returns (quarterly)

asset_returns_tbl <- prices %>% 
    
    group_by(symbol) %>%  
    
    tq_transmute(select     = adjusted, 
                 mutate_fun = periodReturn, 
                 period     = "quarterly", 
                 type      = "log") %>% 
    
    slice(-1) %>% 
    
    ungroup() %>% 
    
    set_names(c("asset", "date", "returns"))

3 Weight of each asset

symbols <- asset_returns_tbl %>% distinct(asset) %>% pull() 
symbols
## [1] "BRK-B" "CVLG"  "JNJ"   "JPM"   "LLY"   "NVDA"  "RTX"   "XPEV"
weights <- c(0.15, 0.20, 0.175, 0.075, 0.10, 0.075, 0.075, 0.15)
weights
## [1] 0.150 0.200 0.175 0.075 0.100 0.075 0.075 0.150
w_tbl <- tibble(symbols, weights)
w_tbl
## # A tibble: 8 × 2
##   symbols weights
##   <chr>     <dbl>
## 1 BRK-B     0.15 
## 2 CVLG      0.2  
## 3 JNJ       0.175
## 4 JPM       0.075
## 5 LLY       0.1  
## 6 NVDA      0.075
## 7 RTX       0.075
## 8 XPEV      0.15

4 Build a portfolio

portfolio_returns_tbl <- asset_returns_tbl %>%
    
    tq_portfolio(assets_col   = asset, 
                 returns_col  = returns, 
                 weights      = w_tbl, 
                 rebalance_on = "quarters")

portfolio_returns_tbl
## # A tibble: 20 × 2
##    date       portfolio.returns
##    <date>                 <dbl>
##  1 2020-09-30           0.0906 
##  2 2020-12-31           0.154  
##  3 2021-03-31           0.0977 
##  4 2021-06-30           0.106  
##  5 2021-09-30           0.0284 
##  6 2021-12-31           0.111  
##  7 2022-03-31          -0.100  
##  8 2022-06-30          -0.0324 
##  9 2022-09-30          -0.169  
## 10 2022-12-30           0.108  
## 11 2023-03-31           0.0386 
## 12 2023-06-30           0.172  
## 13 2023-09-29           0.0358 
## 14 2023-12-29           0.0239 
## 15 2024-03-28           0.0312 
## 16 2024-06-28           0.0309 
## 17 2024-09-30           0.143  
## 18 2024-12-31          -0.0181 
## 19 2025-03-31           0.0968 
## 20 2025-05-19           0.00105

5 Plot: Portfolio Histogram and Density

portfolio_returns_tbl %>%
    
    ggplot(mapping = aes(x = portfolio.returns)) +
    geom_histogram(fill = "cornflowerblue", binwidth = 0.01) + 
    geom_density() + 
    
    # Formatting
    scale_x_continuous(labels = scales::percent_format()) +
    
    labs(x = "returns", 
         y = "distribution", 
         title = "Portfolio Histogram & Density")

What return should you expect from the portfolio in a typical quarter?

Looking at the graph we can see that most of the returns are just below 5% or around 10%. There are some negative exceptions and a few quarters with returns around 15%. The average return based on this graph should be right under 10%.