# Load packages
# Core
library(tidyverse)
library(tidyquant)
library(ggrepel)
Visualize expected returns and risk to make it easier to compare the performance of multiple assets and portfolios.
Choose your stocks.
from 2020-12-31 to 2026-10-08
symbols <- c("TSM", "MU", "NOW", "MRVL", "PLTR")
prices <- tq_get(x = symbols,
get = "stock.prices",
from = "2020-12-31",
to = "2026-10-08")
prices
## # A tibble: 7,240 × 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,230 more rows
asset_returns_tbl2 <- prices %>%
group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = "monthly",
type = "log") %>%
slice(-1) %>%
ungroup() %>%
set_names(c("asset", "date", "returns"))
symbols <- asset_returns_tbl2 %>% 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_tbl2 <- tibble(symbols, weight)
weight_tbl2
## # 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
library(PerformanceAnalytics)
portfolio_returns_tbl2 <-
asset_returns_tbl2 %>%
tq_portfolio(assets_col = asset,
returns_col = returns,
weights = weight_tbl2,
rebalence_on = "months")
portfolio_returns_tbl2
## # A tibble: 70 × 2
## date portfolio.returns
## <date> <dbl>
## 1 2021-01-29 0.127
## 2 2021-02-26 -0.102
## 3 2021-03-31 -0.0373
## 4 2021-04-30 -0.0186
## 5 2021-05-28 -0.0149
## 6 2021-06-30 0.106
## 7 2021-07-30 -0.0408
## 8 2021-08-31 0.0589
## 9 2021-09-30 -0.0457
## 10 2021-10-29 0.0731
## # ℹ 60 more rows
portfolio_sd_tidyquant_bulitin_percent2 <- portfolio_returns_tbl2 %>%
tq_performance(Ra = portfolio.returns, performance_fun = table.Stats) %>%
select(Stdev) %>%
mutate(tq_sd = round(Stdev, 4))
portfolio_sd_tidyquant_bulitin_percent2
## # A tibble: 1 × 2
## Stdev tq_sd
## <dbl> <dbl>
## 1 0.101 0.101
portfolio_mean_tidyquant_bulitin_percent2 <- mean(portfolio_returns_tbl2$portfolio.returns)
portfolio_mean_tidyquant_bulitin_percent2
## [1] 0.01944229
sd_mean_tbl2 <- asset_returns_tbl2 %>%
group_by(asset) %>%
tq_performance(Ra = returns,
performance_fun = table.Stats) %>%
select(Mean = ArithmeticMean, Stdev) %>%
ungroup() %>%
add_row(tibble(asset = "Portfolio",
Mean = portfolio_mean_tidyquant_bulitin_percent2,
Stdev = portfolio_sd_tidyquant_bulitin_percent2$tq_sd))
sd_mean_tbl2
## # A tibble: 6 × 3
## asset Mean Stdev
## <chr> <dbl> <dbl>
## 1 MRVL 0.0259 0.171
## 2 MU 0.0385 0.162
## 3 NOW 0.0032 0.107
## 4 PLTR 0.0301 0.196
## 5 TSM 0.0222 0.0969
## 6 Portfolio 0.0194 0.101
sd_mean_tbl2 %>%
ggplot(aes(x = Stdev, y = Mean, colour = asset)) +
geom_point() +
ggrepel::geom_text_repel(aes(label = asset))
rolling_sd_tbl2 <- portfolio_returns_tbl2 %>%
tq_mutate(select = portfolio.returns,
mutate_fun = rollapply,
width = 24,
FUN = sd,
col_rename = "rolling_sd") %>%
na.omit() %>%
select(date, rolling_sd)
rolling_sd_tbl2
## # A tibble: 47 × 2
## date rolling_sd
## <date> <dbl>
## 1 2022-12-30 0.0845
## 2 2023-01-31 0.0887
## 3 2023-02-28 0.0871
## 4 2023-03-31 0.0880
## 5 2023-04-28 0.0880
## 6 2023-05-31 0.100
## 7 2023-06-30 0.0971
## 8 2023-07-31 0.0988
## 9 2023-08-31 0.0985
## 10 2023-09-29 0.0984
## # ℹ 37 more rows
rolling_sd_tbl2 %>%
ggplot(aes(x = date, y = rolling_sd)) +
geom_line(color = "violet") +
#Formatting
scale_y_continuous(labels = scales::percent_format()) +
# Labeling
labs(x = NULL,
y = NULL,
title = "24 - Months Rolling Volatility") +
theme(plot.title = element_text(hjust = 0.5))
How should you expect your portfolio to perform relative to its assets in the portfolio? Would you invest all your money in any of the individual stocks instead of the portfolio? Discuss both in terms of expected return and risk.
When looking at the portfolio return isolated from risk, the portfolio generates a relative low return compared to majority of the assets in the portfolio. As graphic 1 shows, stock “NOW” is pulling down the return quite significantly. I will however address that a 2% monthly return is not bad at all, and would be beating the S&P50, by growing 24% in the period of 12 months.
The portfolio do however, have a low standard deviation compared to the holdings, where there are the stocks TSM and NOW that provides this diversification, and reduction in Stdev. The highest yielding stocks MU, PLTR, and MRVL have almost twice as large deviation. That means that one could feel more comfortable / secure in the portfolio yielding its average return, vs. the three top stocks.
There is primarily two stocks that could compare with the portfolio. 1. TSM: This is a clear choose, as the Stdev is lower than the portfolio, meaning it is less risky, while its return is higher. 2. MU: This stock have a much higher risk, but also yields twice the return, meaning that it technically would grow by 48% on a yearly basis. What I realistically would do, is to remove NOW from the portfolio, and rather up the %share of TSM and MU, to maximize the return and Stdev. See bellow for illustration.
#Adjusted Portfolio
symbols_A <- c("TSM", "MU", "MRVL", "PLTR")
prices_A <- tq_get(x = symbols_A,
get = "stock.prices",
from = "2020-12-31",
to = "2026-10-08")
prices_A
## # A tibble: 5,792 × 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.
## # ℹ 5,782 more rows
asset_returns_tbl_A <- prices_A %>%
group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = "monthly",
type = "log") %>%
slice(-1) %>%
ungroup() %>%
set_names(c("asset", "date", "returns"))
symbols_A <- asset_returns_tbl_A %>% distinct(asset) %>% pull
symbols_A
## [1] "MRVL" "MU" "PLTR" "TSM"
weight_A <- c(0.35, 0.30, 0.25, 0.10)
weight_A
## [1] 0.35 0.30 0.25 0.10
weight_tbl_A <- tibble(symbols_A, weight_A)
weight_tbl_A
## # A tibble: 4 × 2
## symbols_A weight_A
## <chr> <dbl>
## 1 MRVL 0.35
## 2 MU 0.3
## 3 PLTR 0.25
## 4 TSM 0.1
library(PerformanceAnalytics)
portfolio_returns_tbl_A <-
asset_returns_tbl_A %>%
tq_portfolio(assets_col = asset,
returns_col = returns,
weights = weight_tbl_A,
rebalence_on = "months")
portfolio_returns_tbl_A
## # A tibble: 70 × 2
## date portfolio.returns
## <date> <dbl>
## 1 2021-01-29 0.151
## 2 2021-02-26 -0.0927
## 3 2021-03-31 -0.0197
## 4 2021-04-30 -0.0396
## 5 2021-05-28 0.0141
## 6 2021-06-30 0.102
## 7 2021-07-30 -0.0578
## 8 2021-08-31 0.0270
## 9 2021-09-30 -0.0414
## 10 2021-10-29 0.0639
## # ℹ 60 more rows
portfolio_sd_tidyquant_bulitin_percent_A <- portfolio_returns_tbl_A %>%
tq_performance(Ra = portfolio.returns, performance_fun = table.Stats) %>%
select(Stdev) %>%
mutate(tq_sd = round(Stdev, 4))
portfolio_sd_tidyquant_bulitin_percent_A
## # A tibble: 1 × 2
## Stdev tq_sd
## <dbl> <dbl>
## 1 0.123 0.123
portfolio_mean_tidyquant_bulitin_percent_A <- mean(portfolio_returns_tbl_A$portfolio.returns)
portfolio_mean_tidyquant_bulitin_percent_A
## [1] 0.02568467
sd_mean_tbl_A <- asset_returns_tbl_A %>%
group_by(asset) %>%
tq_performance(Ra = returns,
performance_fun = table.Stats) %>%
select(Mean = ArithmeticMean, Stdev) %>%
ungroup() %>%
add_row(tibble(asset = "Portfolio",
Mean = portfolio_mean_tidyquant_bulitin_percent_A,
Stdev = portfolio_sd_tidyquant_bulitin_percent_A$tq_sd))
sd_mean_tbl_A
## # A tibble: 5 × 3
## asset Mean Stdev
## <chr> <dbl> <dbl>
## 1 MRVL 0.0259 0.171
## 2 MU 0.0385 0.162
## 3 PLTR 0.0301 0.196
## 4 TSM 0.0222 0.0969
## 5 Portfolio 0.0257 0.123
sd_mean_tbl_A %>%
ggplot(aes(x = Stdev, y = Mean, colour = asset)) +
geom_point() +
ggrepel::geom_text_repel(aes(label = asset))