# Load packages
# Core
library(tidyverse)
library(tidyquant)
Visualize and compare skewness of your portfolio and its assets.
symbols <- c("Asker.st", "Atco-B.st", "Axfo.st", "Bahn-b.st", "BRK-B", "Cers", "LLY", "Embrac-b.st", "Indu-c.st", "Inve-b.st", "Inwi.st", "Novo-b.co", "NVDA", "Yubico.st")
prices <- tq_get(x = symbols,
get = "stock.prices",
from = "2020-04-01",
to = "2025-06-01")
prices
## # A tibble: 16,672 × 8
## symbol date open high low close volume adjusted
## <chr> <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Asker.st 2025-03-27 83 87.2 80.2 83.7 16441271 83.7
## 2 Asker.st 2025-03-28 83 84.0 81.7 82 1262083 82
## 3 Asker.st 2025-03-31 81.3 81.9 80.1 80.5 626988 80.5
## 4 Asker.st 2025-04-01 80.8 82.2 80.6 81.9 356628 81.9
## 5 Asker.st 2025-04-02 81.9 82.1 80.9 82.1 576561 82.1
## 6 Asker.st 2025-04-03 81 81.8 80.1 80.7 235131 80.7
## 7 Asker.st 2025-04-04 80.5 81.2 77.3 78.6 780928 78.6
## 8 Asker.st 2025-04-07 74.8 80.1 71.4 77.8 377461 77.8
## 9 Asker.st 2025-04-08 79.2 79.9 75 77 371563 77
## 10 Asker.st 2025-04-09 76.1 78.7 72.8 74.2 1171607 74.2
## # ℹ 16,662 more rows
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 <- asset_returns_tbl %>% distinct(asset) %>% pull()
symbols
## [1] "Asker.st" "Atco-B.st" "Axfo.st" "BRK-B" "Bahn-b.st"
## [6] "Cers" "Embrac-b.st" "Indu-c.st" "Inve-b.st" "Inwi.st"
## [11] "LLY" "NVDA" "Novo-b.co" "Yubico.st"
weights <- c(0.0314, 0.0133, 0.0136, 0.0589, 0.0112, 0.0068, 0.0201, 0.1858, 0.2298, 0.0584, 0.0892, 0.2504, 0.0168, 0.0143)
weights
## [1] 0.0314 0.0133 0.0136 0.0589 0.0112 0.0068 0.0201 0.1858 0.2298 0.0584
## [11] 0.0892 0.2504 0.0168 0.0143
w_tbl <- tibble(symbols, weights)
w_tbl
## # A tibble: 14 × 2
## symbols weights
## <chr> <dbl>
## 1 Asker.st 0.0314
## 2 Atco-B.st 0.0133
## 3 Axfo.st 0.0136
## 4 BRK-B 0.0589
## 5 Bahn-b.st 0.0112
## 6 Cers 0.0068
## 7 Embrac-b.st 0.0201
## 8 Indu-c.st 0.186
## 9 Inve-b.st 0.230
## 10 Inwi.st 0.0584
## 11 LLY 0.0892
## 12 NVDA 0.250
## 13 Novo-b.co 0.0168
## 14 Yubico.st 0.0143
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: 68 × 2
## date returns
## <date> <dbl>
## 1 2020-05-29 0.0285
## 2 2020-06-30 0.0121
## 3 2020-07-31 0.0243
## 4 2020-08-31 0.0373
## 5 2020-09-30 0.0430
## 6 2020-10-30 -0.0622
## 7 2020-11-30 0.0746
## 8 2020-12-30 0.0297
## 9 2020-12-31 0.0128
## 10 2021-01-29 0.0187
## # ℹ 58 more rows
portfolio_skew_tidyquant_builtin_percent <- portfolio_returns_tbl %>%
tq_performance(Ra = returns,
performance_fun = table.Stats) %>%
select(Skewness)
portfolio_skew_tidyquant_builtin_percent
## # A tibble: 1 × 1
## Skewness
## <dbl>
## 1 -0.964
# Data transformation: calculate skewness
asset_skewness_tbl <- asset_returns_tbl %>%
group_by(asset) %>%
summarise(skew = skewness(returns)) %>%
ungroup() %>%
# Add portfolio skewness
add_row(tibble(asset = "Portfolio",
skew = skewness(portfolio_returns_tbl$returns)))
asset_skewness_tbl
## # A tibble: 15 × 2
## asset skew
## <chr> <dbl>
## 1 Asker.st 0
## 2 Atco-B.st 0.152
## 3 Axfo.st 0.0381
## 4 BRK-B -0.262
## 5 Bahn-b.st 0.158
## 6 Cers -0.125
## 7 Embrac-b.st -1.36
## 8 Indu-c.st -0.0815
## 9 Inve-b.st -0.492
## 10 Inwi.st -0.297
## 11 LLY -0.170
## 12 NVDA -0.458
## 13 Novo-b.co -1.50
## 14 Yubico.st 0.854
## 15 Portfolio -0.964
# Plot Skewness
asset_skewness_tbl %>%
ggplot(aes(x = asset, y = skew, color = asset)) +
geom_point() +
ggrepel::geom_text_repel(aes(label = asset),
data = asset_skewness_tbl %>%
filter(asset == "Portfolio")) +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 6))
labs(y = "Skewness")
## $y
## [1] "Skewness"
##
## attr(,"class")
## [1] "labels"
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.
Yes, the best example in this graph is Yubico. Yubico has a moderate skewness of close to 1, this means that the returns are asymmetrical with mostly small negative returns and the occasional extreme positive return. This could indicate that Yubico is an opportunistic asset but with higher risk. The portfolio shows a more negative skewness which indicates small positive returns with the occasional sharp loss. Furthermore, this makes sense since the portfolio shows very stable returns and smaller risk, the occasional sharp downfalls are likely macro related.