# Load packages
# 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.2
## ✔ 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
library(ggrepel)
library(dplyr)
library(ggplot2)
library(PerformanceAnalytics)
library(tibble)
Visualize and compare skewness of your portfolio and its assets.
Choose your stocks.
from 2012-12-31 to 2017-12-31
symbols <- c("WMT", "COST", "TGT", "HD", "LOW")
prices <- tq_get(x = symbols,
get = "stock.prices",
from = "2012-12-31",
to = "2017-12-31")
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"))
# symbols
symbols <- asset_returns_tbl %>% distinct(asset) %>% pull()
symbols
## [1] "COST" "HD" "LOW" "TGT" "WMT"
# 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 COST 0.25
## 2 HD 0.25
## 3 LOW 0.2
## 4 TGT 0.2
## 5 WMT 0.1
# ?tq_portfolio
portfolio_returns_tbl <- asset_returns_tbl %>%
tq_portfolio(assets_col = asset,
returns_col = returns,
weights = w_tbl,
rebalance_on = "months",
col_rename = "returns")
## Warning in check_weights(weights, assets_col, map, x): Sum of weights does not
## equal 1.
portfolio_returns_tbl
## # A tibble: 60 × 2
## date returns
## <date> <dbl>
## 1 2013-01-31 0.0507
## 2 2013-02-28 0.0143
## 3 2013-03-28 0.0393
## 4 2013-04-30 0.0312
## 5 2013-05-31 0.0341
## 6 2013-06-28 -0.00859
## 7 2013-07-31 0.0494
## 8 2013-08-30 -0.0491
## 9 2013-09-30 0.0242
## 10 2013-10-31 0.0286
## # ℹ 50 more rows
portfolio_returns_tbl %>%
tq_performance(Ra = returns,
Rb = NULL,
performance_fun = table.Stats) %>%
select(Kurtosis)
## # A tibble: 1 × 1
## Kurtosis
## <dbl>
## 1 -0.497
asset_skew_tbl <- asset_returns_tbl %>%
group_by(asset) %>%
summarise(Skewness = skewness(returns)) %>%
ungroup()
# 2. Skewness for the portfolio
portfolio_skew <- skewness(portfolio_returns_tbl$returns)
# 3. Combine into one table
skew_compare_tbl <- bind_rows(
asset_skew_tbl,
tibble(asset = "Portfolio", Skewness = portfolio_skew)
)
# 4. Plot skewness comparison
ggplot(skew_compare_tbl, aes(x = asset, y = Skewness)) +
geom_col() +
labs(
title = "Skewness Comparison: Assets vs Portfolio",
x = "Asset / Portfolio",
y = "Skewness"
) +
theme_minimal()
Is any asset in your portfolio more likely to return extreme positive returns than your portfolio collectively? Discuss in terms of skewness. You may also refer to the distribution of returns you plotted in Code along 4.