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

Immo Funds

library(familyoffice)

sixfunds <- familyoffice::fo_exchange("six.mutual")

immofunds <- sixfunds |> 
  filter(AssetClassDesc == "Real Estate",
         UnderlyingGeographicalDesc == "Switzerland",
         TradingBaseCurrency == "CHF", FundCurrency == "CHF") |> 
  select(FundLongName, ValorSymbol, ValorNumber, ISIN, IssuerNameFull, ManagementFee)

immofunds |> 
  write_csv("immofunds/immofunds.csv")
immofunds <- read_csv("immofunds/immofunds.csv")

get_swiss_fund_data <- function(id) {
  url <- paste0("https://www.swissfunddata.ch/sfdpub/de/funds/excelData/", id)
  temp <- tempfile(fileext = ".csv")
  
  # handle error if file not there or some other error when downloading
  tryCatch(download.file(url, temp, mode = "wb"), error = function(e) return(NULL))
  
  if (file.exists(temp)) {
  data <- read_csv2(temp, skip = 2, col_types = cols(.default = col_character()))
    return(data)
  } else {
    return(NULL)
  }
}

immofunds_pricedata <- immofunds |> 
  mutate(data = map(SwissFundData, get_swiss_fund_data))

library(familyoffice)

immofunds_pricedata_six <- immofunds_pricedata |> 
  mutate(sixdata = map(ISIN, fo_get)) |> 
  select(-data)


immofunds_pricedata |> 
  saveRDS("immofunds/immofunds_pricedata.RDS")

immofunds_pricedata_six |> 
  saveRDS("immofunds/immofunds_pricedata_six.RDS")
immofunds_pricedata <- readRDS("immofunds/immofunds_pricedata.RDS")
immofunds_pricedata_six <- readRDS("immofunds/immofunds_pricedata_six.RDS")
nav <- immofunds_pricedata |> 
  unnest(data) |> 
  transmute(FundLongName, ValorSymbol, ValorNumber, ISIN, IssuerNameFull,
            Date = ymd(Date),
            `Net Asset Value` = as.numeric(`Net Asset Value`)) |> 
  filter(!is.na(`Net Asset Value`))

prices <- immofunds_pricedata_six |> 
  unnest(sixdata) |> 
  transmute(ValorNumber,
            date,
            close)

df <- full_join(nav, prices,
          by = c("ValorNumber" = "ValorNumber", "Date" = "date")) |> 
  arrange(FundLongName, ISIN, Date) |> 
  group_by(FundLongName) |> 
  mutate(close = na.locf0(close),
         `Net Asset Value` = na.locf0(`Net Asset Value`)) |> 
  mutate(Agio = close/`Net Asset Value` - 1) |> 
  slice_max(Date)

df |> 
  filter(!is.na(Agio)) |> 
  ggplot(aes(x = reorder(FundLongName, Agio), y = Agio)) +
  geom_col() +
  geom_text_repel(aes(label = scales::percent(Agio, accuracy = 0.01)), nudge_y = 0.01) +
  coord_flip() +
  labs(title = "Swiss Immo Funds Agio",
       x = "Fund",
       y = "Agio") +
  theme(axis.text.y = element_text(size = 8))

Tax exemption?

url <- "https://www.ictax.admin.ch/extern/de.html#/security/CH0118768057/20231231"

# download page to temp first then read with rvest
temp <- tempfile(fileext = ".html")
# pretend to be a browser
download.file(url, temp, mode = "wb", headers = c("User-Agent" = "Mozilla/5.0"))
page <- read_html(temp)
page |> html_text() |> cat()