# 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)

Goal

Visualize and compare skewness of your portfolio and its assets.

Choose your stocks.

from 2012-12-31 to 2017-12-31

1 Import stock prices

symbols <- c("WMT", "COST", "TGT", "HD", "LOW")
 
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 a weight to each asset

# 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

4 Build a portfolio

# ?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

5 Calculate Skewness

portfolio_returns_tbl %>%
 
    tq_performance(Ra = returns,
                   Rb = NULL,
                   performance_fun = table.Stats) %>%
    select(Kurtosis)
## # A tibble: 1 × 1
##   Kurtosis
##      <dbl>
## 1   -0.497

6 Plot: Skewness Comparison

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.