# Standard library
# Third-party
# Tulip core
# Tulip data sources
from tulip.data.haver import (
get_collection as get_collection_from_haver,
get_series as get_series_from_haver,
)
# Tulip analysis and visualization
# Tulip mania specific
from tulip.core import TulipCollection, TulipSeries, merge_collections
from tulip.data.gs import GSClient as gs
from IPython.display import Markdown, display
import pandas as pd
from IPython.display import Markdown, HTML
from tulip.data.bloomberg import BloombergClient as bb
from tulip.data.haver import HaverClient as hc
from tulip.plots import plot_lines
from tulip.core import *
from tulip.data.gs import GSClient as gs
from tulip.analysis.country_related.analytics import summarize_gs_eco_fct
from tulip.core import merge_collections
from tulip.genai import iris
from tulip_mania.columns import columns
from tulip_mania.notebook_related import display_chart, display_two_charts
import pycountry
from IPython.display import Markdown, HTML, display
Germany¶
# ========================================
# PARAMETERS & DATA FETCHING
# ========================================
# Country identifiers
ISO_2 = "DE"
BBERG_ISO_2 = ISO_2
pyctry = pycountry.countries.get(alpha_2=ISO_2)
ISO_3 = pyctry.alpha_3
ctry_name = pyctry.name
goldman_ctry_id = ISO_2
bloomberg_ctry_prefix = "DE"
# ----------------------------------------
# HAVER DATA
# ----------------------------------------
# Growth Stats
prices_dict = {
"EU HICP": "F023H@EUDATA",
"H-CPI (Bundesbank)": "DENPCHBK@GERMANY",
"H-CPI Core (Bundesbank)": "DENPCHXG@GERMANY",
"Retail Price Index": "DENPVS@GERMANY",
"Producer Price Index": "DEGPPT@GERMANY",
# "Bundesbank Projection": "DEAPH@GERMANY",
}
prices_collection = get_collection_from_haver(prices_dict)
prices_collection.good_is = -1
prices_collection = prices_collection.apply("yoy")
prices_collection = prices_collection.append(get_series_from_haver("DEAPH@GERMANY"))
prices_collection.dashboard.table()# ========================================
# PARAMETERS & DATA FETCHING
# ========================================
# Country identifiers
ISO_2 = "DE"
BBERG_ISO_2 = ISO_2
pyctry = pycountry.countries.get(alpha_2=ISO_2)
ISO_3 = pyctry.alpha_3
ctry_name = pyctry.name
goldman_ctry_id = ISO_2
bloomberg_ctry_prefix = "DE"
# ----------------------------------------
# HAVER DATA
# ----------------------------------------
# Growth Stats
growth_stats_dict = {
"Real GDP YoY": "DESNGDPQ@GERMANY",
"Fixed Investment": "DESNFQ@GERMANY",
"Govt Consumption": "DESNCPQ@GERMANY",
"Private Consumption": "DESNCVQ@GERMANY",
"Exports": "DESNXQ@GERMANY",
"Imports": "DESNMQ@GERMANY",
}
growth_stats_collection = get_collection_from_haver(growth_stats_dict).apply("yoy")
growth_stats_collection["DESNMQ@GERMANY"].good_is = -1
# Retail Sales
retail_sales = hc.get_series("yryr%(DESTU47@GERMANY)")
retail_sales.info.title = "Retail Sales YoY"
# Real GDP Growth (for single chart)
real_gdp_yoy = hc.get_series("DEWNGDPW@GERMANY")
# Prices
prices_dict = {
"EU HICP": "F023H@EUDATA",
"H-CPI (Bundesbank)": "DENPCHBK@GERMANY",
"H-CPI Core (Bundesbank)": "DENPCHXG@GERMANY",
"Retail Price Index": "DENPVS@GERMANY",
"Producer Price Index": "DEGPPT@GERMANY",
# "Bundesbank Projection": "DEAPH@GERMANY",
}
prices_collection = get_collection_from_haver(prices_dict)
# ZEW Inflation Survey
zew_inf_survey = hc.get_series("DENVEIDE@GERMANY")
# Employment
employment_dict = {
"Unemployment Rate": "DESEUR@GERMANY",
"BA-X Job Index": "DESEBAX@GERMANY",
"Unemployment in broad Sense": "DESE001B@GERMANY",
"Job Vacancies": "DESE250U@GERMANY",
"Labor Force": "DESEULF@GERMANY",
"Ifo Employment Barometer": "DESVIE@GERMANY",
"DIHK Hiring Intentions": "DENVHEIN@GERMANY",
}
employment_collection = get_collection_from_haver(employment_dict)
employment_collection["DESEUR@GERMANY"].good_is = -1
employment_collection["DESE001B@GERMANY"].good_is = -1
# Output Gap
output_gap = hc.get_series("F134FAAA@AMECO")
# Trade
trade_dict = {
"Current Account Balance % GDP": "DENBCW@GERMANY",
"Current Account Balance Goods % GDP": "DENBGW@GERMANY",
"Current Account Balance Services % GDP": "DENBSW@GERMANY",
}
trade_collection = get_collection_from_haver(trade_dict)
# Surveys
surveys_dict = {
"ZEW Economic Sentiment": "DENVZCG@GERMANY",
"Sentix": "DENVSGX@GERMANY",
"Sentix Current": "DENVSH6@GERMANY",
"Sentix Future": "DENVSH0@GERMANY",
"GfK Consumer": "DENVCC@GERMANY",
"DIHK Current": "DENVHECN@GERMANY",
"DIHK Future": "DENVHBEN@GERMANY",
"ZEW EA Current Macroeconomic Conditions": "DENVZCE@GERMANY",
"ZEW EA Macroeconomic Expectations 6m": "DENVZEE@GERMANY",
}
surveys_collection = get_collection_from_haver(surveys_dict)
# Government Finance
government_finance_dict = {
"Public Debt": "DENFDGT@GERMANY",
"Govt Budget Surplus/Deficit": "DEYFGBZ@GERMANY",
}
government_finance_collection = get_collection_from_haver(government_finance_dict)
# ----------------------------------------
# BLOOMBERG DATA
# ----------------------------------------
# PMIs
pmi_tickers = {
"MPMIDESA Index": "HCOB Germany Services PMI",
"MPMIDECA Index": "HCOB Germany Composite PMI",
}
pmi_collection = bb.create_collection(list(pmi_tickers.keys()))
for i, title in enumerate(pmi_tickers.values()):
pmi_collection[i].info.title = title
# Industrial Production
indprod_tickers = {
"GRIPIMOM Index": "Industrial Production SA MoM",
"GRIORTMM Index": "Factory Orders MoM",
}
indprod_collection = bb.create_collection(list(indprod_tickers.keys()))
for i, title in enumerate(indprod_tickers.values()):
indprod_collection[i].info.title = title
# Nowcasts
try:
nowcasts = bb.create_collection(["BENWEAGC Index", "BENWDEGC Index"])
except Exception as e:
nowcasts = None
print(f"Nowcasts not available: {e}")# ========================================
# MAIN SUMMARY
# ========================================
# TODO: Categorize collections into thematic buckets
growth_collection = merge_collections(
growth_stats_collection, TulipCollection([retail_sales])
)
inflation_collection = prices_collection
unemployment_and_slack_collection = merge_collections(
employment_collection, TulipCollection([output_gap])
)
fiscal_collection = government_finance_collection
other_collection = merge_collections(trade_collection, surveys_collection)
country_collection = merge_collections(
growth_collection,
inflation_collection,
unemployment_and_slack_collection,
fiscal_collection,
other_collection,
)
overall_summary = iris.summarize(
country_collection, "Highlight recent developments that could matter for markets"
)
overall_summary.html()1. Growth: Activity & Output¶
1.1 Economic Forecasts (Consensus)¶
# Goldman Sachs Economic Forecasts
try:
gs_eco_fct = gs.get_eco_forecast(geographyId=ISO_2)
gs_summary = summarize_gs_eco_fct(gs_eco_fct)
gs_summary = gs_summary[~gs_summary.index.str.contains("ngdp")].to_frame().T
gs_summary.style.set_caption(f"Goldman {ctry_name} Economic Forecasts").format(
precision=2
)
except Exception as e:
display(Markdown(f"*Goldman Sachs forecasts not available for {ctry_name}: {e}*"))1.2 Growth Nowcasts & Real-Time Indicators¶
# Goldman Sachs Current Activity Indicator (CAI)
try:
cai_series = gs.get_CAI_series(
geographyId=ISO_2,
metricName=[
"CAI_HEADLINE",
"CAI_CONTRIBUTION_TYPE_HARD",
"CAI_CONTRIBUTION_TYPE_SOFT",
],
startDate="1980-01-01",
)
cai_series = cai_series.set_index("metricName", append=True)["metricValue"].unstack(
"metricName"
)
cai_series.columns = ["Hard", "Soft", "Headline"]
cai_plot = plot_lines(
cai_series,
show_0=True,
title=f"<b>{ctry_name} Current Activity Indicator</b> Updated: {pd.Timestamp.today().strftime('%Y-%m-%d')}",
years_limit=4,
tick_suffix="%",
source="Goldman Sachs",
)
cai_plot.show()
except Exception as e:
display(Markdown(f"*CAI not available for {ctry_name}: {e}*"))# Bloomberg Nowcasts
if nowcasts:
nowcasts.dashboard.table()
nowcasts.dashboard.plots(show_0=True)1.3 GDP Growth & Components¶
# Real GDP Growth
real_gdp_yoy.plot(show_0=True, tick_suffix="%", source="Haver")# GDP Components
growth_stats_collection.dashboard.table()growth_stats_collection.dashboard.plots(show_0=True)# Nominal GDP Growth
hc.get_series("DENNGDPP@GERMANY").plot(show_0=True, tick_suffix="%")1.4 Business Activity Surveys¶
# PMIs
pmi_collection.dashboard.table()pmi_collection.dashboard.plots(hlines=50)1.5 Retail Sales & Consumer Activity¶
retail_sales.plot(years_limit=2, tick_suffix="%", show_0=True)1.6 Industrial Production & Manufacturing¶
indprod_collection.dashboard.table()indprod_collection.dashboard.plots(years_limit=3, mma=12, tick_suffix="%", show_0=True)1.7 High Frequency Indicators¶
Development of the German labour market based on the LinkedIn Hiring Rate
2. Prices: Inflation & Wages¶
2.1 Headline & Core Inflation¶
prices_collection.dashboard.table()prices_df = prices_collection.df
fig = plot_lines(
prices_df.iloc[:, :3],
years_limit=8,
title="<b>Key Inflation Measures</b>",
tick_suffix="%",
source="Bundesbank",
)
fig.add_hline(2, line_width=1, annotation_text="Target")2.2 Inflation Expectations & Surveys¶
zew_inf_survey.plot(show_0=True)2.3 Wage Growth & Labor Costs¶
3. Slack: Output Gap & Capacity Utilization¶
3.1 Output Gap Estimates¶
output_gap.plot(show_0=True)3.2 Capacity Utilization¶
4. Employment: Labor Market Conditions¶
4.1 Unemployment Rate & Labor Force¶
employment_collection.dashboard.table()employment_collection.dashboard.plots(years_limit=10)5. Financial Conditions¶
5.1 Business & Consumer Surveys¶
surveys_collection.dashboard.table()surveys_collection.dashboard.plots(years_limit=3, show_0=True)5.2 External Balance (Current Account, Trade)¶
trade_collection.dashboard.table()trade_collection.dashboard.plots(show_0=True, mma=4)5.3 Credit Growth & Debt Levels¶
6. Fiscal Conditions¶
6.1 Budget Balance & Public Debt¶
government_finance_collection.dashboard.table()government_finance_collection.dashboard.plots()7. Asset Pricing¶
from tulip_mania.notebook_related import notebook_updated
notebook_updated()