1. Companies

Two TWSE-listed common stocks (no ETFs, funds or preferred shares), one row each from the TWSE ISIN register (strMode = 2). The ISIN site was returning HTTP 404, so the rows come from the ISIN data mirrored in the twstock package.

isin <- read.csv(text = r"-(stock_id,stock_name,listing_date,industry,isin
2317,鴻海,1991-06-18,其他電子業,TW0002317005
2330,台積電,1994-09-05,半導體業,TW0002330008)-",
  colClasses = "character", encoding = "UTF-8") %>%
  mutate(listing_date = as.Date(listing_date),
         label = paste0(stock_id, " ", c("Hon Hai", "TSMC")))
knitr::kable(isin %>% select(stock_id, stock_name, listing_date, industry, isin))
stock_id stock_name listing_date industry isin
2317 鴻海 1991-06-18 其他電子業 TW0002317005
2330 台積電 1994-09-05 半導體業 TW0002330008

2. Years listed

isin %>%
  mutate(years_listed = as.numeric(Sys.Date() - listing_date) / 365.25) %>%
  ggplot(aes(label, years_listed, fill = label)) +
  geom_col(width = 0.5, show.legend = FALSE) +
  geom_text(aes(label = paste0(round(years_listed, 1), " yrs\n(", format(listing_date, "%Y-%m-%d"), ")")),
            vjust = -0.3) +
  scale_fill_manual(values = c("#c0392b", "#1f4e79")) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.2))) +
  labs(title = "How long each company has been listed on the TWSE",
       x = NULL, y = "Years since listing") +
  theme_minimal(base_size = 13)

3. Price performance (FinMind)

Daily closing prices pulled live from FinMind (TaiwanStockPrice), rebased to 100 at the start so the two companies can be compared. A free token avoids rate limits: Sys.setenv(FINMIND_TOKEN = "your_token").

get_px <- function(id) {
  q <- list(dataset = "TaiwanStockPrice", data_id = id,
            start_date = format(Sys.Date() - 365 * 3, "%Y-%m-%d"))
  tok <- Sys.getenv("FINMIND_TOKEN"); if (nzchar(tok)) q$token <- tok
  r <- tryCatch(GET("https://api.finmindtrade.com/api/v4/data", query = q, timeout(60)),
                error = function(e) NULL)
  if (is.null(r) || status_code(r) != 200) return(NULL)
  d <- fromJSON(content(r, "text", encoding = "UTF-8"))$data
  if (is.null(d) || !nrow(d)) return(NULL)
  d %>% transmute(stock_id = id, date = as.Date(date), close)
}
px <- bind_rows(lapply(isin$stock_id, get_px))

if (nrow(px) == 0) {
  cat("FinMind price data unavailable right now. Re-knit with a token or later.")
} else {
  px <- px %>% left_join(isin %>% select(stock_id, label), by = "stock_id") %>%
    group_by(label) %>% arrange(date) %>% mutate(index = close / first(close) * 100) %>% ungroup()
  ggplot(px, aes(date, index, colour = label)) +
    geom_line(linewidth = 0.9) +
    geom_hline(yintercept = 100, linetype = "dashed", colour = "grey50") +
    scale_colour_manual(values = c("#c0392b", "#1f4e79")) +
    labs(title = "Closing price, rebased to 100 (last 3 years)", x = NULL, y = "Index (start = 100)",
         colour = NULL, caption = "Source: FinMind TaiwanStockPrice") +
    theme_minimal(base_size = 13) + theme(legend.position = "top")
}

Sources: TWSE ISIN register (via twstock 1.5.1), FinMind API v4.