options(repos = c(CRAN = "https://cloud.r-project.org"))

Stock Price

The Stock price is collected from March 1st, a month ahead of liberation day to May 10th.

stocks <- tq_get(c("ATCO-A.ST", "SINCH.ST", "INVE-B.st", "SSAB-B.ST", "SAAB-B.ST", "AXFO.ST", "VOLCAR-B.ST", "NDA-SE.ST", "ERIC-B.ST", "CAST.ST", "ORRON.ST", "AZN.ST"),
                 get = "stock.prices",
                 from = "2025-03-01",
                 to = "2025-05-10")
stocks
## # A tibble: 564 × 8
##    symbol    date        open  high   low close  volume adjusted
##    <chr>     <date>     <dbl> <dbl> <dbl> <dbl>   <dbl>    <dbl>
##  1 ATCO-A.ST 2025-03-03  183.  184.  181.  181. 5851286     179.
##  2 ATCO-A.ST 2025-03-04  178.  179.  174.  175. 5849265     174.
##  3 ATCO-A.ST 2025-03-05  180.  185.  178.  184. 6462212     183.
##  4 ATCO-A.ST 2025-03-06  186.  186.  179.  183. 5369088     181.
##  5 ATCO-A.ST 2025-03-07  181.  184.  179.  183. 6084395     182.
##  6 ATCO-A.ST 2025-03-10  184.  185.  179.  179. 3915631     177.
##  7 ATCO-A.ST 2025-03-11  182.  182.  175.  175. 4600879     173.
##  8 ATCO-A.ST 2025-03-12  178.  179.  176.  177. 6365358     175.
##  9 ATCO-A.ST 2025-03-13  175.  178.  174.  176. 3017065     174.
## 10 ATCO-A.ST 2025-03-14  175.  177.  175.  177. 3440299     175.
## # ℹ 554 more rows

Stock Prices Graphed

stocks %>%
    
    ggplot(aes(x = date, y = adjusted, color = symbol)) +
    geom_line()

Improved Graph

library(yfR)
library(ggplot2)
library(dplyr)
library(scales)
## 
## Attaching package: 'scales'
## The following object is masked from 'package:purrr':
## 
##     discard
## The following object is masked from 'package:readr':
## 
##     col_factor
# Load data
tickers <- c("ATCO-A.ST", "SINCH.ST", "INVE-B.st", "SSAB-B.ST", "SAAB-B.ST", "AXFO.ST", "VOLCAR-B.ST", "NDA-SE.ST", "ERIC-B.ST", "CAST.ST", "ORRON.ST", "AZN.ST")

df_stocks <- yf_get(tickers = tickers, 
                        first_date = as.Date("2025-03-01"), 
                        last_date = as.Date("2025-05-10"))
## 
## ── Running yfR for 12 stocks | 2025-03-01 --> 2025-05-10 (70 days) ──
## 
## ℹ Downloading data for benchmark ticker ^GSPC
## ℹ (1/12) Fetching data for ATCO-A.ST
## !    - not cached
## ✔    - cache saved successfully
## ✔    - got 47 valid rows (2025-03-03 --> 2025-05-09)
## ✔    - got 96% of valid prices -- Nice!
## ℹ (2/12) Fetching data for AXFO.ST
## !    - not cached
## ✔    - cache saved successfully
## ✔    - got 47 valid rows (2025-03-03 --> 2025-05-09)
## ✔    - got 96% of valid prices -- Good job vincentsmac!
## ℹ (3/12) Fetching data for AZN.ST
## !    - not cached
## ✔    - cache saved successfully
## ✔    - got 47 valid rows (2025-03-03 --> 2025-05-09)
## ✔    - got 96% of valid prices -- Time for some tea?
## ℹ (4/12) Fetching data for CAST.ST
## !    - not cached
## ✔    - cache saved successfully
## ✔    - got 47 valid rows (2025-03-03 --> 2025-05-09)
## ✔    - got 96% of valid prices -- Youre doing good!
## ℹ (5/12) Fetching data for ERIC-B.ST
## !    - not cached
## ✔    - cache saved successfully
## ✔    - got 47 valid rows (2025-03-03 --> 2025-05-09)
## ✔    - got 96% of valid prices -- Youre doing good!
## ℹ (6/12) Fetching data for INVE-B.st
## !    - not cached
## ✔    - cache saved successfully
## ✔    - got 47 valid rows (2025-03-03 --> 2025-05-09)
## ✔    - got 96% of valid prices -- Well done vincentsmac!
## ℹ (7/12) Fetching data for NDA-SE.ST
## !    - not cached
## ✔    - cache saved successfully
## ✔    - got 47 valid rows (2025-03-03 --> 2025-05-09)
## ✔    - got 96% of valid prices -- You got it vincentsmac!
## ℹ (8/12) Fetching data for ORRON.ST
## !    - not cached
## ✔    - cache saved successfully
## ✔    - got 47 valid rows (2025-03-03 --> 2025-05-09)
## ✔    - got 96% of valid prices -- All OK!
## ℹ (9/12) Fetching data for SAAB-B.ST
## !    - not cached
## ✔    - cache saved successfully
## ✔    - got 47 valid rows (2025-03-03 --> 2025-05-09)
## ✔    - got 96% of valid prices -- Youre doing good!
## ℹ (10/12) Fetching data for SINCH.ST
## !    - not cached
## ✔    - cache saved successfully
## ✔    - got 47 valid rows (2025-03-03 --> 2025-05-09)
## ✔    - got 96% of valid prices -- All OK!
## ℹ (11/12) Fetching data for SSAB-B.ST
## !    - not cached
## ✔    - cache saved successfully
## ✔    - got 47 valid rows (2025-03-03 --> 2025-05-09)
## ✔    - got 96% of valid prices -- You got it vincentsmac!
## ℹ (12/12) Fetching data for VOLCAR-B.ST
## !    - not cached
## ✔    - cache saved successfully
## ✔    - got 47 valid rows (2025-03-03 --> 2025-05-09)
## ✔    - got 96% of valid prices -- Mas bah tche, que coisa linda!
## ℹ Binding price data
## 
## ── Diagnostics ─────────────────────────────────────────────────────────────────
## ✔ Returned dataframe with 564 rows -- Feliz que nem lambari de sanga!
## ℹ Using 78.4 kB at /var/folders/xv/5h23j4p10m94jp1pvq6296x00000gn/T//Rtmpxj2mCH/yf_cache for 13 cache files
## ℹ Out of 12 requested tickers, you got 12 (100%)
# Calculate % change from first available price
df_pct_change <- df_stocks %>%
  group_by(ticker) %>%
  arrange(ref_date) %>%
  mutate(pct_change = 100 * (price_adjusted / first(price_adjusted) - 1))

# Plot % change
ggplot(df_pct_change, aes(x = ref_date, y = pct_change, color = ticker)) +
  geom_line(lindewidth = 1) +
  labs(title = "Stock Performance (% Change from Start)",
       x = "Date", y = "% Change", color = "Stock") +
  scale_y_continuous(labels = scales::percent_format(scale = 1)) +
  theme_minimal()
## Warning in geom_line(lindewidth = 1): Ignoring unknown parameters: `lindewidth`

library(ggthemes)

ggplot(df_pct_change, aes(x = ref_date, y = pct_change, color = ticker)) +
  geom_line(size = 1.2) +
  scale_color_tableau(name = "Stock") +  # Color-blind friendly and distinct
  labs(title = "Stock Performance (% Change from Start)",
       x = "Date", y = "% Change") +
  theme_economist() +  # or try theme_fivethirtyeight()
  scale_y_continuous(labels = scales::percent_format(scale = 1))
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning in check_pal_n(n, max_n): This palette can handle a maximum of 10
## values.You have supplied 12.
## Warning: Removed 94 rows containing missing values or values outside the scale range
## (`geom_line()`).