QuantumLearner commited on
Commit
b2450bf
·
verified ·
1 Parent(s): eb57765

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +242 -0
app.py ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas_datareader.data as web
3
+ import yfinance as yf
4
+ import datetime
5
+ import plotly.graph_objs as go
6
+
7
+ # Set up the layout
8
+ st.set_page_config(layout="wide")
9
+
10
+ # App title and description
11
+ st.title("Key Economic Recession Indicators")
12
+ st.markdown("""
13
+ This tool allows you to visualize and analyze various recession indicators over time.
14
+ The shaded areas in the charts represent historical recession periods.
15
+ Use the checkboxes in the sidebar to choose the indicators you'd like to explore.
16
+ """)
17
+
18
+ # Sidebar for chart selection
19
+ st.sidebar.header("Select Indicators")
20
+ indicators = {
21
+ 'Sahm Recession Indicator': 'SAHMREALTIME',
22
+ 'U.S. Recession Probabilities': 'Recession_Probabilities',
23
+ 'Yield Spread (10Y - 2Y)': 'Yield_Spread',
24
+ 'Stock Market (S&P 500)': 'SP500',
25
+ 'VIX': 'VIX',
26
+ 'Treasury Rates': ('GS10', 'DGS2', 'DGS1MO', 'TB3MS'),
27
+ 'Federal Funds Rate': 'FEDFUNDS',
28
+ 'Unemployment Rate': 'UNRATE',
29
+ 'Nonfarm Payrolls': 'PAYEMS',
30
+ 'Jobless Claims': 'ICSA',
31
+ 'Retail Sales': 'RSXFS',
32
+ 'Industrial Production': ('INDPRO', 'INDPRO_PCT'),
33
+ 'Housing Starts': 'HOUST',
34
+ 'Consumer Confidence': 'UMCSENT',
35
+ 'Inflation (CPI)': ('CPIAUCSL', 'CPIAUCSL_PCT')
36
+ }
37
+
38
+ selected_indicators = {key: st.sidebar.checkbox(key, value=True) for key in indicators.keys()}
39
+
40
+ # Define start and end dates
41
+ start_date = datetime.datetime(1920, 1, 1)
42
+ end_date = datetime.datetime.today()
43
+ extended_end_date = end_date + datetime.timedelta(days=120)
44
+
45
+ # Define recession periods (as before)
46
+ crash_periods = {
47
+ '1929-08-01': '1933-03-01',
48
+ '1937-05-01': '1938-06-01',
49
+ '1945-02-01': '1945-10-01',
50
+ '1948-11-01': '1949-10-01',
51
+ '1953-07-01': '1954-05-01',
52
+ '1957-08-01': '1958-04-01',
53
+ '1960-04-01': '1961-02-01',
54
+ '1969-12-01': '1970-11-01',
55
+ '1973-11-01': '1975-03-01',
56
+ '1980-01-01': '1980-07-01',
57
+ '1981-07-01': '1982-11-01',
58
+ '1990-07-01': '1991-03-01',
59
+ '2001-03-01': '2001-11-01',
60
+ '2007-12-01': '2009-06-01',
61
+ '2020-02-01': '2020-04-01'
62
+ }
63
+
64
+ # Run button
65
+ if st.sidebar.button('Run Analysis'):
66
+ # Fetch the data from FRED
67
+ sahm_recession_indicator = web.DataReader('SAHMREALTIME', 'fred', start_date, end_date)
68
+ retail_sales = web.DataReader('RSXFS', 'fred', start_date, end_date)
69
+ industrial_production = web.DataReader('INDPRO', 'fred', start_date, end_date)
70
+ unemployment_rate = web.DataReader('UNRATE', 'fred', start_date, end_date)
71
+ inflation = web.DataReader('CPIAUCSL', 'fred', start_date, end_date)
72
+ nonfarm_payrolls = web.DataReader('PAYEMS', 'fred', start_date, end_date)
73
+ jobless_claims = web.DataReader('ICSA', 'fred', start_date, end_date)
74
+ consumer_confidence = web.DataReader('UMCSENT', 'fred', start_date, end_date)
75
+ housing_starts = web.DataReader('HOUST', 'fred', start_date, end_date)
76
+ treasury_rate_10y = web.DataReader('GS10', 'fred', start_date, end_date)
77
+ treasury_rate_2y = web.DataReader('DGS2', 'fred', start_date, end_date)
78
+ treasury_rate_1m = web.DataReader('DGS1MO', 'fred', start_date, end_date)
79
+ treasury_rate_3m = web.DataReader('TB3MS', 'fred', start_date, end_date)
80
+ federal_funds_rate = web.DataReader('FEDFUNDS', 'fred', start_date, end_date)
81
+ recession_probabilities = web.DataReader('RECPROUSM156N', 'fred', start_date, end_date)
82
+
83
+ # Rename columns for clarity
84
+ recession_probabilities.columns = ['Recession_Probabilities']
85
+
86
+ # Fetch the data from Yahoo Finance
87
+ sp500 = yf.download('^GSPC', start=start_date, end=end_date)['Adj Close']
88
+ vix = yf.download('^VIX', start=start_date, end=end_date)['Adj Close']
89
+
90
+ # Calculate percentage changes for relevant indicators
91
+ industrial_production_pct = industrial_production.pct_change() * 100
92
+ inflation_pct = inflation.pct_change() * 100
93
+
94
+ # Rename columns for clarity
95
+ industrial_production_pct = industrial_production_pct.rename(columns={'INDPRO': 'INDPRO_PCT'})
96
+ inflation_pct = inflation_pct.rename(columns={'CPIAUCSL': 'CPIAUCSL_PCT'})
97
+
98
+ # Combine all data into a single DataFrame, aligning by date
99
+ combined_data = sahm_recession_indicator.join([
100
+ retail_sales, industrial_production, industrial_production_pct,
101
+ unemployment_rate, inflation, inflation_pct,
102
+ sp500.rename('SP500'), nonfarm_payrolls, jobless_claims,
103
+ consumer_confidence, housing_starts, treasury_rate_10y, treasury_rate_2y, treasury_rate_1m, treasury_rate_3m, federal_funds_rate, vix.rename('VIX'),
104
+ recession_probabilities
105
+ ], how='outer')
106
+
107
+ # Interpolate missing values for alignment
108
+ combined_data = combined_data.interpolate(method='time')
109
+
110
+ # Calculate the yield spread
111
+ combined_data['Yield_Spread'] = combined_data['GS10'] - combined_data['DGS2']
112
+
113
+ # Plot each selected series
114
+ for key, column in indicators.items():
115
+ if selected_indicators[key]:
116
+ fig = go.Figure()
117
+
118
+ # Add recession shading
119
+ for peak, trough in crash_periods.items():
120
+ fig.add_shape(
121
+ type="rect",
122
+ xref="x",
123
+ yref="paper",
124
+ x0=peak,
125
+ y0=0,
126
+ x1=trough,
127
+ y1=1,
128
+ fillcolor="gray",
129
+ opacity=0.3,
130
+ layer="below",
131
+ line_width=0,
132
+ )
133
+
134
+ if isinstance(column, tuple):
135
+ if column == ('INDPRO', 'INDPRO_PCT'):
136
+ # Plot industrial production and its percentage change on dual y-axes
137
+ fig.add_trace(go.Scatter(x=combined_data.index, y=combined_data['INDPRO'], mode='lines', name='Industrial Production'))
138
+ fig.add_trace(go.Scatter(x=combined_data.index, y=combined_data['INDPRO_PCT'], mode='lines', name='Industrial Production % Change', yaxis='y2'))
139
+
140
+ # Create a secondary y-axis and place the legend inside the plot area
141
+ fig.update_layout(
142
+ yaxis2=dict(
143
+ title="Industrial Production % Change",
144
+ overlaying='y',
145
+ side='right'
146
+ ),
147
+ legend=dict(
148
+ x=0.02,
149
+ y=0.95,
150
+ traceorder='normal',
151
+ bgcolor='rgba(255, 255, 255, 0.5)',
152
+ bordercolor='rgba(0, 0, 0, 0)'
153
+ )
154
+ )
155
+ elif column == ('CPIAUCSL', 'CPIAUCSL_PCT'):
156
+ # Plot inflation and its percentage change on dual y-axes
157
+ fig.add_trace(go.Scatter(x=combined_data.index, y=combined_data['CPIAUCSL'], mode='lines', name='Inflation (CPI)'))
158
+ fig.add_trace(go.Scatter(x=combined_data.index, y=combined_data['CPIAUCSL_PCT'], mode='lines', name='Inflation % Change', yaxis='y2'))
159
+
160
+ # Create a secondary y-axis and place the legend inside the plot area
161
+ fig.update_layout(
162
+ yaxis2=dict(
163
+ title="Inflation % Change",
164
+ overlaying='y',
165
+ side='right'
166
+ ),
167
+ legend=dict(
168
+ x=0.02,
169
+ y=0.95,
170
+ traceorder='normal',
171
+ bgcolor='rgba(255, 255, 255, 0.5)',
172
+ bordercolor='rgba(0, 0, 0, 0)'
173
+ )
174
+ )
175
+ elif column == ('GS10', 'DGS2', 'DGS1MO', 'TB3MS'):
176
+ # Plot multiple Treasury rates in the same subplot
177
+ for col in column:
178
+ fig.add_trace(go.Scatter(x=combined_data.index, y=combined_data[col], mode='lines', name=col))
179
+
180
+ # Place the legend inside the plot area
181
+ fig.update_layout(
182
+ legend=dict(
183
+ x=0.02,
184
+ y=0.95,
185
+ traceorder='normal',
186
+ bgcolor='rgba(255, 255, 255, 0.5)',
187
+ bordercolor='rgba(0, 0, 0, 0)'
188
+ )
189
+ )
190
+ else:
191
+ fig.add_trace(go.Scatter(x=combined_data.index, y=combined_data[column], mode='lines', name=key))
192
+
193
+ # Add horizontal threshold line for Sahm Recession Indicator
194
+ if column == 'SAHMREALTIME':
195
+ fig.add_hline(y=0.5, line=dict(color="red", dash="dash"), annotation_text="Recession Threshold", annotation_position="bottom right")
196
+
197
+ # Update layout with detailed date formatting
198
+ fig.update_layout(
199
+ title=key,
200
+ xaxis_title='Date',
201
+ yaxis_title=key,
202
+ xaxis=dict(
203
+ tickformat="%Y", # Yearly ticks
204
+ tickmode="linear",
205
+ dtick="M36", # Ticks every 12 months, M24 Every 2 years and 5 years is M60
206
+ showspikes=True,
207
+ spikemode='across',
208
+ spikesnap='cursor',
209
+ spikethickness=1
210
+ ),
211
+ hovermode="x unified",
212
+ hoverlabel=dict(
213
+ bgcolor="white",
214
+ font_size=12,
215
+ font_family="Rockwell"
216
+ )
217
+ )
218
+ fig.update_xaxes(
219
+ showgrid=True,
220
+ gridwidth=1,
221
+ gridcolor='LightGray',
222
+ tickangle=45,
223
+ tickformatstops=[
224
+ dict(dtickrange=[None, "M1"], value="%b %d, %Y"), # Format as "Month Day, Year" for better granularity
225
+ dict(dtickrange=["M1", None], value="%Y") # Year format for larger intervals
226
+ ]
227
+ )
228
+
229
+ # Ensure full date is shown on hover
230
+ fig.update_traces(
231
+ hovertemplate='%{x|%b %d, %Y}<br>%{y}<extra></extra>'
232
+ )
233
+
234
+ st.plotly_chart(fig, use_container_width=True)
235
+
236
+ hide_streamlit_style = """
237
+ <style>
238
+ #MainMenu {visibility: hidden;}
239
+ footer {visibility: hidden;}
240
+ </style>
241
+ """
242
+ st.markdown(hide_streamlit_style, unsafe_allow_html=True)