# Load packages

# Core
library(tidyverse)
library(tidyquant)

Goal

Calculate and visualize your portfolio’s beta.

Choose your stocks and the baseline market.

from 2012-12-31 to present

1 Import stock prices

symbols <- c("TSM", "MU", "NOW", "MRVL", "PLTR")

prices <- tq_get(x = symbols,
                 get = "stock.prices",
                 from = "2020-12-31",
                 to = "2026-11-01")
prices
## # A tibble: 7,325 × 8
##    symbol date        open  high   low close   volume adjusted
##    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
##  1 TSM    2020-12-31  110.  110.  108.  109.  4909500     99.5
##  2 TSM    2021-01-04  111.  114.  110.  112. 11262100    102. 
##  3 TSM    2021-01-05  112.  115.  112.  113. 10583600    103. 
##  4 TSM    2021-01-06  114.  116.  113.  116. 10609300    105. 
##  5 TSM    2021-01-07  119.  123.  118.  121. 13556100    111. 
##  6 TSM    2021-01-08  126.  126.  117.  119. 18976800    108. 
##  7 TSM    2021-01-11  120.  124.  119.  123. 12006800    112. 
##  8 TSM    2021-01-12  125.  125.  122.  123  14163200    112. 
##  9 TSM    2021-01-13  124.  125.  118   119. 20650500    109. 
## 10 TSM    2021-01-14  123.  135.  122.  126. 37125400    115. 
## # ℹ 7,315 more rows

2 Convert prices to returns (monthly)

asset_returns_tbl <- prices %>%
    
    group_by(symbol) %>%
    
    tq_transmute(select = adjusted,
                 mutate_fun = periodReturn,
                 period = "monthly",
                 type = "log") %>%
    
    slice(-1) %>% 
    ungroup() %>%

set_names(c("asset", "date", "returns"))

3 Assign a weight to each asset (change the weigting scheme)

symbols <- asset_returns_tbl %>% distinct(asset) %>% pull

symbols
## [1] "MRVL" "MU"   "NOW"  "PLTR" "TSM"
weight <- c(0.15, 0.20, 0.30, 0.25, 0.10)
weight
## [1] 0.15 0.20 0.30 0.25 0.10
weight_tbl <- tibble(symbols, weight)
weight_tbl
## # A tibble: 5 × 2
##   symbols weight
##   <chr>    <dbl>
## 1 MRVL      0.15
## 2 MU        0.2 
## 3 NOW       0.3 
## 4 PLTR      0.25
## 5 TSM       0.1

4 Build a portfolio

library(PerformanceAnalytics)

portfolio_returns_tbl <- asset_returns_tbl %>%
    
    tq_portfolio(assets_col = asset,
                 returns_col = returns,
                 weights = weight_tbl,
                 rebalance_on = "months",
                 col_rename = "returns")

portfolio_returns_tbl
## # A tibble: 70 × 2
##    date       returns
##    <date>       <dbl>
##  1 2021-01-29  0.127 
##  2 2021-02-26 -0.0768
##  3 2021-03-31 -0.0370
##  4 2021-04-30 -0.0170
##  5 2021-05-28 -0.0150
##  6 2021-06-30  0.112 
##  7 2021-07-30 -0.0438
##  8 2021-08-31  0.0689
##  9 2021-09-30 -0.0484
## 10 2021-10-29  0.0685
## # ℹ 60 more rows

5 Calculate CAPM Beta

5.1 Get market returns

market_returns_tbl <- tq_get(x = "QQQ",
                 get = "stock.prices",
                from = "2020-12-31",
                 to = "2026-11-01") %>%
    
# Convert prices to monthly returns
    
    tq_transmute(select = adjusted,
                 mutate_fun = periodReturn, 
                 period = "monthly",
                 type = "log",
                 col_rename = "returns") %>%
    slice(-1)

5.2 Join returns

portfolio_market_returns_tbl <- left_join(market_returns_tbl, portfolio_returns_tbl, by = "date") %>%
    set_names("date", "market_returns", "portfolio_returns")

portfolio_market_returns_tbl
## # A tibble: 70 × 3
##    date       market_returns portfolio_returns
##    <date>              <dbl>             <dbl>
##  1 2021-01-29        0.00261            0.127 
##  2 2021-02-26       -0.00134           -0.0768
##  3 2021-03-31        0.0170            -0.0370
##  4 2021-04-30        0.0574            -0.0170
##  5 2021-05-28       -0.0121            -0.0150
##  6 2021-06-30        0.0607             0.112 
##  7 2021-07-30        0.0282            -0.0438
##  8 2021-08-31        0.0413             0.0689
##  9 2021-09-30       -0.0585            -0.0484
## 10 2021-10-29        0.0757             0.0685
## # ℹ 60 more rows

5.3 CAPM Beta

portfolio_market_returns_tbl %>%
    
    tq_performance(Ra = portfolio_returns, Rb = market_returns, performance_fun = CAPM.beta)
## # A tibble: 1 × 1
##   CAPM.beta.1
##         <dbl>
## 1        1.39

6 Plot: Scatter with regression line

portfolio_market_returns_tbl %>%
    
    ggplot(aes(x = market_returns,
               y = portfolio_returns)) +
    
    geom_point(color = "cornflowerblue") +
    geom_smooth(method = "lm", se = FALSE, linewidth = 1.5, color = tidyquant::palette_light() [3]) +
    
    labs(y = "Portfolio Returns",
         x = "Market Returns")

How sensitive is your portfolio to the market? Discuss in terms of the beta coefficient. Does the plot confirm the beta coefficient you calculated?

The portfolio have a relatively high CAMP beta of 1.39, meaning that the stock is 39% more sensitive to market movements, than a stock or portfolio matching the market beta of 1. In practice, this means that if the market is up 10%, we expect the portfolio to have gained a 13.9% Reversely, if the market were to decline 10%, the portfolio would be expected to loose an additional 3.9% more than the market. The plot does demonstrate the beta coeffriciency pretty well, by the plots being centered around the linear regression line. There are however, some exceptions, where the portfolio returns a 200% return (1:3 coefficiency), and by so, pull up the beta, as the regression line is based on an avg.