# Load packages
# Core
library(tidyverse)
library(tidyquant)
Visualize expected returns and risk to make it easier to compare the performance of multiple assets and portfolios.
Choose your stocks.
from 2012-12-31 to 2017-12-31
symbols <- c("JPM", "MS", "DNB.OL", "NDA-FI.HE")
prices <- tq_get(x = symbols,
get = "stock.prices",
from = "2017-01-01",
to = "2023-12-31") %>%
filter(!is.na(close))
asset_returns_tbl <-prices %>%
group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = "quarterly",
type = "log") %>%
ungroup() %>%
set_names(c("asset", "date", "returns"))
asset_returns_tbl
## # A tibble: 112 Ă— 3
## asset date returns
## <chr> <date> <dbl>
## 1 JPM 2017-03-31 0.0125
## 2 JPM 2017-06-30 0.0455
## 3 JPM 2017-09-29 0.0495
## 4 JPM 2017-12-29 0.119
## 5 JPM 2018-03-29 0.0331
## 6 JPM 2018-06-29 -0.0488
## 7 JPM 2018-09-28 0.0851
## 8 JPM 2018-12-31 -0.138
## 9 JPM 2019-03-29 0.0444
## 10 JPM 2019-06-28 0.107
## # ℹ 102 more rows
#symbols
symbols <- asset_returns_tbl %>% distinct(asset) %>% pull()
symbols
## [1] "JPM" "MS" "DNB.OL" "NDA-FI.HE"
#weights
weights <- c(0.25, 0.25, 0.25, 0.25)
weights
## [1] 0.25 0.25 0.25 0.25
w_tbl <- tibble(symbols, weights)
w_tbl
## # A tibble: 4 Ă— 2
## symbols weights
## <chr> <dbl>
## 1 JPM 0.25
## 2 MS 0.25
## 3 DNB.OL 0.25
## 4 NDA-FI.HE 0.25
# ?tq_portfolio
portfolio_returns_tbl <- asset_returns_tbl %>%
tq_portfolio(assets_col = asset,
returns_col = returns,
weights = w_tbl,
rebalance_on = "months")
portfolio_returns_tbl
## # A tibble: 33 Ă— 2
## date portfolio.returns
## <date> <dbl>
## 1 2017-03-31 0.0324
## 2 2017-06-30 0.0531
## 3 2017-09-29 0.0704
## 4 2017-12-29 0.00773
## 5 2018-03-28 0.0000821
## 6 2018-03-29 -0.00541
## 7 2018-06-29 -0.0306
## 8 2018-09-28 0.0706
## 9 2018-12-28 -0.119
## 10 2018-12-31 -0.0829
## # ℹ 23 more rows
portfolio_sd_tidyquant_builtin_percent <- portfolio_returns_tbl %>%
tq_performance(Ra = portfolio.returns,
performance_fun = table.Stats) %>%
select(Stdev) %>%
mutate(tq_sd = round(Stdev, 4))
portfolio_sd_tidyquant_builtin_percent
## # A tibble: 1 Ă— 2
## Stdev tq_sd
## <dbl> <dbl>
## 1 0.103 0.103
# Mean of portfolio returns
portfolio_mean_tidyquant_builtin_percent <- mean(portfolio_returns_tbl$portfolio.returns)
portfolio_mean_tidyquant_builtin_percent
## [1] 0.02366598
# Expected Returns vs Risk
sd_mean_tbl <- asset_returns_tbl %>%
group_by(asset)%>%
tq_performance(Ra = returns,
performance_fun = table.Stats) %>%
select(Mean = ArithmeticMean, Stdev) %>%
ungroup() %>%
# Add portfolio sd
add_row(tibble(asset = "Portfolio",
Mean = portfolio_mean_tidyquant_builtin_percent,
Stdev = portfolio_sd_tidyquant_builtin_percent$tq_sd))
sd_mean_tbl
## # A tibble: 5 Ă— 3
## asset Mean Stdev
## <chr> <dbl> <dbl>
## 1 JPM 0.0309 0.143
## 2 MS 0.0346 0.149
## 3 DNB.OL 0.0311 0.113
## 4 NDA-FI.HE 0.0184 0.127
## 5 Portfolio 0.0237 0.103
sd_mean_tbl %>%
ggplot(aes(x = Stdev, y = Mean, color = asset)) +
geom_point() +
ggrepel::geom_text_repel(aes(label = asset))
Return: The portfolio has a lower expected return (mean around 0.025) compared to most of the individual assets, such as MS (Morgan Stanley), which has the highest expected return (about 0.035), and JPM (JPMorgan Chase), which also has a higher expected return than the portfolio (about 0.03).
Risk: The portfolio has the lowest standard deviation (about 0.11), indicating it carries less risk compared to any of the individual stocks.
Based on the risk-return tradeoff, the portfolio offers a safer and more stable investment. If you’re seeking higher returns and can tolerate more risk, MS or JPM may be attractive, but they carry much higher volatility. Investing all money in a single stock would expose you to more risk, and the portfolio offers a better balance for long-term risk management.
Currently, all assets in my portfolio belong to the same asset class and sector. By leveraging the principles of diversification, my portfolio could benefit from incorporating a broader range of assets across different sectors and asset classes.