library(tidyverse)
library(lubridate)
library(scales)
library(ggrepel)
library(tidyquant)
library(jsonlite)
theme_set(theme_minimal())
invisible(Sys.setlocale("LC_TIME", "en_US.UTF-8"))

library(knitr)
library(kableExtra)
library(familyoffice)

stocks <- fo_exchange("six.stocks")

stocks |> saveRDS("data/sixetfs/stocks.RDS")
stocks <- readRDS("data/sixetfs/stocks.RDS")
profiles <- tibble()
i <- 0
while(T) {
  cat(i, "\n")
  url <- paste0("https://financialmodelingprep.com/stable/profile-bulk?part=", i, "&apikey=", read_lines("data/key.txt"))
  temp <- read_csv(url)
  if (is.null(temp)) break
  if (nrow(temp) == 0) break
  if (i > 10) break
  profiles <- bind_rows(profiles, temp)
  i <- i + 1
}

profiles |> saveRDS("data/sixstocks/profiles.RDS")
profiles <- readRDS("data/sixstocks/profiles.RDS")
swissstocks <- profiles |> 
  filter(exchange == "SIX",
         country == "CH",
         currency == "CHF",
         !isEtf,
         isActivelyTrading,
         !isAdr,
         !isFund) |> 
  group_by(companyName) |> 
  slice_min(price, n = 1) |> 
  ungroup()
set.seed(123)
swissstocks |> 
  ggplot(aes(x = fullTimeEmployees+1, y = marketCap/10^6, color = sector, size = marketCap)) +
  geom_point(alpha = 0.8) +
  geom_point(color = "grey40", shape = 21) +
  geom_text_repel(aes(label = ifelse(fullTimeEmployees > 5000, companyName, NA_character_)), size = 2, color = "grey30") +
  geom_text_repel(aes(label = ifelse(fullTimeEmployees <= 5000, companyName, NA_character_)), size = 2, color = "grey30", max.iter = 200, max.overlaps = 3) +
  scale_x_log10(labels = scales::number_format(), breaks = c(1, 10, 100, 1000, 10000, 100000)) +
  scale_y_log10(labels = scales::number_format(), breaks = c(1, 10, 100, 1000, 10000, 100000)) +
  labs(title = "Swiss Stock Exchange listed Companies",
       subtitle = "Market cap vs. number of employees",
       x = "Number of employees",
       y = "Market cap (in million CHF)",
       color = "Sector") +
  theme(legend.position = "none")

swissstocks |> 
  arrange(sector, desc(marketCap)) |>
  group_by(sector) |>
  summarise(
    marketCapAll = (sum(marketCap)/10^9) |> round(digits = 1) |> paste0(" Mrd."),
    top3 = paste0(
      head(paste0(companyName, " (", round(marketCap / 1e9, 1), ")"), 3),
      collapse = ", "
    )
  ) |> 
  knitr::kable() |> 
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover"))
sector marketCapAll top3
Basic Materials 152.4 Mrd. Holcim Ltd (51.7), Sika AG (37.4), Givaudan SA (36.8)
Communication Services 29.4 Mrd. Swisscom AG (26.6), TX Group AG (2), APG SGA SA (0.6)
Consumer Cyclical 128.9 Mrd. Compagnie Financière Richemont SA (103.7), The Swatch Group AG (8.7), SIG Group AG (7.6)
Consumer Defensive 263.1 Mrd. Nestlé S.A. (199.2), Galderma Group N (26.3), Chocoladefabriken Lindt & Sprüngli AG (24)
Energy 0.1 Mrd. Meyer Burger Technology AG (0.1)
Financial Services 364.7 Mrd. UBS Group AG (103), Zurich Insurance Group AG (78.5), Swiss Re AG (40.5)
Healthcare 588.6 Mrd. Roche Holding AG (230.8), Novartis AG (188.8), Alcon Inc. (41.3)
Industrials 266.4 Mrd. ABB Ltd (92.1), Schindler Holding AG (28.1), Kuehne + Nagel International AG (24.6)
Real Estate 27.4 Mrd. Swiss Prime Site AG (8), PSP Swiss Property AG (6.2), Allreal Holding AG (2.8)
Technology 31.8 Mrd. Logitech International S.A. (13.7), Temenos AG (5.4), ALSO Holding AG (3.1)
Utilities 8.3 Mrd. BKW AG (8.2), Edisun Power Europe AG (0.1)
# total number of employees
swissstocks |> 
  group_by(sector) |> 
  summarise(employees = sum(fullTimeEmployees)) |>
  filter(employees > 0) |> 
  ggplot(aes(x = reorder(sector, employees), y = employees, fill = sector)) +
  geom_col() +
  geom_text(aes(label = employees |> number()), vjust = -0.1) +
  scale_y_continuous(labels = scales::number_format()) +
  labs(title = "Total number of employees by sector (worldwide of course)",
       subtitle = "Swiss Stock Exchange listed Companies",
       x = "Sector",
       y = "Number of employees",
       fill = "Sector") +
  theme(legend.position = "none",
        # turn x label 45 degrees
        axis.text.x = element_text(angle = 45, hjust = 1))