Ich bin zufällig auf das Projekt SimFin gestoßen und muss es hier weiterempfehlen. Das Projekt sammelt Firmendaten und hat es sich zum Ziel gesetzt diese freizugänglich zu machen. Über eine API und das Paket simfinR können diese Daten schließlich relativ leicht heruntergeladen und direkt analysiert werden. Im Folgenden ein kleines Beispiel, wie einfach der Umgang mit SimFin ist und welchen Mehrwert dieses bietet. Im Folgenden schaue ich in der Liste der verfügbaren Firmen:
CompList = simfinR_get_available_companies(api_key = my_api_key)
head(CompList)
## simId ticker name
## 1 171401 ZYXI ZYNEX INC
## 2 901704 ZYNE Zynerba Pharmaceuticals, Inc.
## 3 994625 ZUO ZUORA INC
## 4 45730 ZUMZ Zumiez Inc
## 5 378251 ZTS Zoetis
## 6 987611 ZSAN Zosano Pharma Corp
Ich nutze die Gelegenheit und suche nachh Fox Corp, dem Eigentümer von Fox News.
CompList[CompList$name == "Fox Corp",]
## simId ticker name
## 1678 885908 FOX Fox Corp
Mit der ID bekomme ich nun die ersten Informationen zu Fox Corp mit folgendem Code:
simfinR_get_info_company(id_sim = 885908, api_key = my_api_key) %>%
as.data.frame()
## simId ticker name employees sectorName sectorCode fyearEnd
## 1 885908 FOX Fox Corp 9000 Entertainment 103001 6
Finanzstatements
Nun kann ich schauen, was die SimFin Datenbank für Finanzstatements bereit hält. Der folgende Code gibt einen ersten Einblick: es gibt eine GuV (pl), Bilanz (bs) und Cashflow-Statements (cf) und sogar berechnete Zahlen wie die trailing twelve months (TTM) Zahlen.
DocumentList = simfinR_get_available_statements(id_sim = 885908, api_key = my_api_key, silent = TRUE)
head(DocumentList)
## period fyear calculated statement id_sim name_sim
## 1 TTM 2020 TRUE pl 885908 Fox Corp
## 2 FY 2020 FALSE pl 885908 Fox Corp
## 3 Q4 2020 TRUE pl 885908 Fox Corp
## 4 H2 2020 TRUE pl 885908 Fox Corp
## 5 9M 2020 FALSE pl 885908 Fox Corp
## 6 Q3 2020 FALSE pl 885908 Fox Corp
Im Folgenden ziehe ich die Ganzjahres-Statements und visualisiere direkt die GuV. Es fällt auf, dass das Ergebnis trotz steigendem Umsatz fällt!
df_FY = simfinR_get_fin_statements(
id_companies = 885908, api_key = my_api_key, type_statements = c("pl", "bs", "cf"),
periods = "FY", years = 2010:2020, cache_folder = "simfin_cache"
)
df_FY %>%
filter(type_statement == "pl") %>%
filter(acc_name == 'Revenue' | acc_name == 'Net Income') %>%
ggplot(aes(x = ref_date, y = acc_value, fill = fct_inorder(acc_name))) +
geom_col(position = "dodge") +
scale_fill_viridis(discrete=TRUE, option="cividis") +
geom_hline(yintercept = 0, color="grey") +
theme_minimal() +
labs(title = 'Fox Corporation', x = '', y = '') +
theme(legend.title = element_blank()) +
scale_y_continuous(labels = unit_format(unit = "m", scale = 1e-6)) +
facet_grid(type_statement~., scales = 'free_y')
Für die Ganzjahreszahlen gibt es leider nur die GuV; die Bilanz gibt es zB nur auf quartärlicher Basis. Entsprechend ziehe ich nun die quartärlichen Daten und visualisiere diese direkt:
df_Qrt = simfinR_get_fin_statements(
id_companies = 885908, api_key = my_api_key, type_statements = c("pl","bs","cf"),
periods = c('Q1','Q2','Q3','Q4'), years = 2010:2020, cache_folder = "simfin_cache"
)
df_Qrt %>%
filter(acc_name == 'Revenue' | acc_name == 'Net Income' |
acc_name == "Total Liabilities" | acc_name == "Long Term Debt" |
acc_name == "Total Equity" | acc_name == 'Cash from Operating Activities') %>%
ggplot(aes(x = ref_date, y = acc_value, fill = fct_inorder(acc_name))) +
geom_col(position = "dodge") +
scale_fill_viridis(discrete=TRUE, option="cividis") +
geom_hline(yintercept = 0, color="grey") +
theme_minimal() +
labs(title = 'Fox Corporation', x = '', y = '') +
theme(legend.title = element_blank()) +
scale_y_continuous(labels = unit_format(unit = "m", scale = 1e-6)) +
facet_grid(type_statement~., scales = 'free_y')
## Warning: Removed 12 rows containing missing values (geom_col).
An sich kann man auch ein bestimmtes Statement laden:
df_Qrt = simfinR_get_fin_statements(
id_companies = 885908, api_key = my_api_key, type_statements = c("pl"),
periods = 'Q2', years = 2020, cache_folder = "simfin_cache"
)
head(df_Qrt)
## company_name company_sector type_statement period year ref_date
## 1 Fox Corp Entertainment pl Q2 2020 2020-06-30
## 2 Fox Corp Entertainment pl Q2 2020 2020-06-30
## 3 Fox Corp Entertainment pl Q2 2020 2020-06-30
## 4 Fox Corp Entertainment pl Q2 2020 2020-06-30
## 5 Fox Corp Entertainment pl Q2 2020 2020-06-30
## 6 Fox Corp Entertainment pl Q2 2020 2020-06-30
## acc_name acc_value tid uid parent_tid display_level
## 1 Revenue 3.778e+09 1 1 4 0
## 2 Sales & Services Revenue NA 3 0 1 1
## 3 Financing Revenue NA 5 0 1 1
## 4 Other Revenue NA 6 0 1 1
## 5 Cost of revenue NA 2 2 4 0
## 6 Cost of Goods & Services NA 7 0 2 1
## check_possible
## 1 FALSE
## 2 FALSE
## 3 FALSE
## 4 FALSE
## 5 FALSE
## 6 FALSE
Der Vorteil, diese Daten direkt zu haben liegt auf der Hand: die Verfügbarkeit aber auch die Möglichkeit, diese Daten zu verarbeiten. Im Folgenden vergleiche ich nun einmal Fox Corp zu Netflix und schaue mir berechnete Kennzahlen an:
df_Qrt_comp = simfinR_get_fin_statements(
id_companies = c("885908", "83548"), api_key = my_api_key,
periods = c('Q1','Q2','Q3','Q4'), years = 2015:2020, cache_folder = "simfin_cache"
)
df_Qrt_comp %>%
select(company_name, ref_date, acc_name, acc_value) %>%
filter(acc_name == 'Revenue' | acc_name == 'Net Income' |acc_name == "Total Liabilities" | acc_name == "Total Assets" | acc_name == "Long Term Debt") %>%
na.omit() %>%
dcast(company_name + ref_date ~ acc_name) %>%
mutate(NetIncome_margin = `Net Income` / Revenue) %>%
mutate(leverage = `Total Liabilities` / `Total Assets`) %>%
mutate(LongTermDebt_Share = `Long Term Debt` / `Total Liabilities`) %>%
select(company_name, ref_date, NetIncome_margin, leverage, LongTermDebt_Share) %>%
melt(., id.vars=c("company_name", "ref_date")) %>%
filter(ref_date > "2018-01-01") %>%
ggplot(aes(x = ref_date, y = value, color = fct_inorder(variable))) +
geom_line() +
geom_point(shape = 21, fill = "white", size = 1, stroke = 1) +
scale_color_viridis(discrete=TRUE, option="cividis") +
geom_hline(yintercept = 0, color="grey") +
theme_minimal() +
labs(title = '',
x = '', y = '') +
theme(legend.title = element_blank()) +
scale_y_continuous(labels = unit_format(unit = "%", scale = 100)) +
facet_grid(company_name~., scales = 'free_y')
## Using acc_value as value column: use value.var to override.
## Warning: Removed 9 row(s) containing missing values (geom_path).
## Warning: Removed 10 rows containing missing values (geom_point).
Zwei Punkte fallen direkt auf: Netflix ist höher verschuldet (leverage = liabilities / assets). Dies ist angesichts des jungen Status erklärbar. Viel interessanter ist, dass die Einkommensmarge bei Netflix sehr viel stabiler als bei Fox Corp ist.
Aktienkurs
Und wie schlagen sich diese Kennzahlen aber auch aktuelle Ereignisse wie die Präsidentschaftswahl im Aktienkurs wider?
df_price = simfinR_get_price_data(id_companies = 885908, api_key = my_api_key)
df_price %>%
ggplot(aes(x = ref_date, y = close_adj)) +
geom_line() +
labs(title = 'Fox Corp',
x = '', y = 'Adjusted Stock Price') +
theme_minimal()
Der Einbruch mit Covid wird sichtbar; im Folgenden zoomen wir auf die Präsidentschaftswahl am Anfang November:
df_price %>%
filter(ref_date > "2020-09-01") %>%
ggplot(aes(x = ref_date, y = close_adj)) +
geom_smooth(span=0.2, se=FALSE, colour="grey") +
geom_line() +
labs(title = 'Fox Corp',
x = '', y = 'Adjusted Stock Price') +
theme_minimal()
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
Photo by SevenStorm JUHASZIMRUS from Pexels