title: “Apply it to your data 10” subtitle: “How sensitive is your portfolio to the market?”

# Core
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.2     ✔ tibble    3.3.0
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.1.0     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(tidyquant)
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo 
## ── Attaching core tidyquant packages ─────────────────────── tidyquant 1.0.11 ──
## ✔ PerformanceAnalytics 2.0.8      ✔ TTR                  0.24.4
## ✔ quantmod             0.4.28     ✔ xts                  0.14.1── Conflicts ────────────────────────────────────────── tidyquant_conflicts() ──
## ✖ zoo::as.Date()                 masks base::as.Date()
## ✖ zoo::as.Date.numeric()         masks base::as.Date.numeric()
## ✖ dplyr::filter()                masks stats::filter()
## ✖ xts::first()                   masks dplyr::first()
## ✖ dplyr::lag()                   masks stats::lag()
## ✖ xts::last()                    masks dplyr::last()
## ✖ PerformanceAnalytics::legend() masks graphics::legend()
## ✖ quantmod::summary()            masks base::summary()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

Goal

Calculate and visualize your portfolio’s beta.

Choose your stocks and the baseline market.

from 2012-12-31 to present

1 Input Stock Prices

symbols <- c("NVDA", "AAPL", "AMD", "INTC", "GOOG")
prices <- tq_get(x = symbols, 
                 get = "stock.prices",
                 from = "2012-12-31",
                 to   = "2017-12-31")

2 Convert prices to returns

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 Weight To Each Asset

# symbols
symbols <- asset_returns_tbl %>% distinct(asset) %>% pull()
symbols
## [1] "AAPL" "AMD"  "GOOG" "INTC" "NVDA"
# weights
weights <- c(0.25, 0.25, 0.2, 0.2, 0.1)
weights
## [1] 0.25 0.25 0.20 0.20 0.10
w_tbl <- tibble(symbols, weights)
w_tbl 
## # A tibble: 5 × 2
##   symbols weights
##   <chr>     <dbl>
## 1 AAPL       0.25
## 2 AMD        0.25
## 3 GOOG       0.2 
## 4 INTC       0.2 
## 5 NVDA       0.1

4 Build a portfolio

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

portfolio_returns_tbl
## # A tibble: 60 × 2
##    date        returns
##    <date>        <dbl>
##  1 2013-01-31 -0.00164
##  2 2013-02-28 -0.00108
##  3 2013-03-28  0.0152 
##  4 2013-04-30  0.0583 
##  5 2013-05-31  0.114  
##  6 2013-06-28 -0.0279 
##  7 2013-07-31  0.0103 
##  8 2013-08-30 -0.0323 
##  9 2013-09-30  0.0532 
## 10 2013-10-31  0.0333 
## # ℹ 50 more rows

5 Calculate CAPM Beta

5.1 Get Market Returns

market_returns_tbl <- tq_get(x = "VOO", 
                 get = "stock.prices",
                 from = "2012-12-31",
                 to   = "2017-12-31") %>%
    
    # Convert prices to 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")

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.38

6 Plot

Scatterplot of returns 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, 
                size = 1.5, color = 
tidyquant::palette_light()[3]) +
    
    labs(y = "Potfolio Returns",
         x = "Market Returns")
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `geom_smooth()` using formula = 'y ~ x'

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

My portfolio is more sensitive than market. This confirms my portfolio’s Beta at 1.38 the line trends slightly lower than a 45 degree angle. As a result of this beta my portfolio follows the trendline but has more differentiation than the trend line of the market. When looking at the scatterplot by portfolio see’s returns lower than the low end of the plot line but higher than the high end of the plot line. Along with seeing a slight higher concentration whenn the market is at 0% growth my portfolio however is generally performing at 0.02% growth.

Line plot of fitted vs actual returns

actual_fitted_long_tbl <- portfolio_market_returns_tbl %>%
    
    # Linear Regression Model
    lm(portfolio_returns ~ market_returns, data = .) %>%
# . meaning: take the value that's been passed on to, here "portfolio_market_returns_tbl"
    
    # Get fitted and actual returns
    broom::augment() %>%
    
    # Add date
    mutate(date = portfolio_market_returns_tbl$date) %>%
# $: Adds a column
    
    select(date, portfolio_returns, .fitted) %>%
    
    # Transform data to long
    pivot_longer(cols = c(portfolio_returns, .fitted), 
                 names_to = "type", 
                 values_to = "returns")
    
actual_fitted_long_tbl %>%
    
    ggplot(aes(x = date, y = returns, color = type)) +
    geom_line()