|
| 1 | +# Import required packages |
| 2 | +import streamlit as st |
| 3 | +import snowflake.connector |
| 4 | +import pandas as pd |
| 5 | + |
| 6 | +# Snowflake connection function |
| 7 | +@st.cache_resource |
| 8 | +def create_snowflake_connection(): |
| 9 | + return snowflake.connector.connect( |
| 10 | + user=st.secrets["snowflake"]["user"], |
| 11 | + password=st.secrets["snowflake"]["password"], |
| 12 | + account=st.secrets["snowflake"]["account"], |
| 13 | + warehouse=st.secrets["snowflake"]["warehouse"], |
| 14 | + database=st.secrets["snowflake"]["database"], |
| 15 | + schema=st.secrets["snowflake"]["schema"] |
| 16 | + ) |
| 17 | + |
| 18 | + |
| 19 | +# Function to load data from Snowflake |
| 20 | +# @st.cache_data() |
| 21 | +def load_data(conn): |
| 22 | + daily_query = "SELECT * FROM FRED_DB.PROD_ANALYTICS.FRED_COMBINED_DAILY" |
| 23 | + weekly_query = "SELECT * FROM FRED_DB.PROD_ANALYTICS.FRED_COMBINED_WEEKLY" |
| 24 | + monthly_query = "SELECT * FROM FRED_DB.PROD_ANALYTICS.FRED_COMBINED_MONTHLY" |
| 25 | + |
| 26 | + daily_agg = pd.read_sql(daily_query, conn) |
| 27 | + weekly_agg = pd.read_sql(weekly_query, conn) |
| 28 | + monthly_agg = pd.read_sql(monthly_query, conn) |
| 29 | + |
| 30 | + return daily_agg, weekly_agg, monthly_agg |
| 31 | + |
| 32 | +def daily_data_analytics(daily_agg): |
| 33 | + st.subheader('Daily Yield Analytics') |
| 34 | + |
| 35 | + # Ensure OBS_DATE is in datetime format |
| 36 | + daily_agg['OBS_DATE'] = pd.to_datetime(daily_agg['OBS_DATE']) |
| 37 | + |
| 38 | + # Get min and max date |
| 39 | + min_date = daily_agg['OBS_DATE'].min() |
| 40 | + max_date = daily_agg['OBS_DATE'].max() |
| 41 | + |
| 42 | + # Date range input |
| 43 | + date_range = st.date_input( |
| 44 | + "Date range:", |
| 45 | + [min_date.date(), max_date.date()], # Convert min/max to .date() |
| 46 | + min_value=min_date.date(), |
| 47 | + max_value=max_date.date(), |
| 48 | + key='date_range' |
| 49 | + ) |
| 50 | + |
| 51 | + # Ensure date_range returns a tuple of two dates |
| 52 | + if isinstance(date_range, tuple) and len(date_range) == 2: |
| 53 | + start_date, end_date = date_range |
| 54 | + start_date = pd.to_datetime(start_date) |
| 55 | + end_date = pd.to_datetime(end_date) |
| 56 | + |
| 57 | + # Apply filtering |
| 58 | + df_filter = daily_agg[(daily_agg['OBS_DATE'] >= start_date) & (daily_agg['OBS_DATE'] <= end_date)] |
| 59 | + # Remove rows where 10Y_YIELD or 2Y_YIELD is 0 |
| 60 | + df_filter = df_filter[(df_filter['10Y_YIELD'] > 0) & (df_filter['2Y_YIELD'] > 0)] |
| 61 | + |
| 62 | + st.line_chart(df_filter, x = 'OBS_DATE', y = ['10Y_YIELD', '2Y_YIELD'], |
| 63 | + height = 500, |
| 64 | + x_label= "Financial Period", |
| 65 | + y_label= "Yield") |
| 66 | + |
| 67 | + data = df_filter[['OBS_DATE', 'SPREAD']] |
| 68 | + |
| 69 | + data['Positive Change'] = data['SPREAD'].apply(lambda x: x if x >= 0 else None) |
| 70 | + data['Negative Change'] = data['SPREAD'].apply(lambda x: x if x < 0 else None) |
| 71 | + |
| 72 | + st.line_chart( |
| 73 | + data.set_index('OBS_DATE')[['Positive Change', 'Negative Change']], |
| 74 | + use_container_width=True |
| 75 | + ) |
| 76 | + |
| 77 | + else: |
| 78 | + st.warning("Please select a valid date range.") |
| 79 | + |
| 80 | +def weekly_data_analytics(weekly_agg): |
| 81 | + st.subheader('Weekly Yield Spread Analytics') |
| 82 | + |
| 83 | + # Ensure WEEK_START is in datetime format |
| 84 | + weekly_agg['WEEK_START'] = pd.to_datetime(weekly_agg['WEEK_START']) |
| 85 | + |
| 86 | + # Get min and max date |
| 87 | + min_date = weekly_agg['WEEK_START'].min() |
| 88 | + max_date = weekly_agg['WEEK_START'].max() |
| 89 | + |
| 90 | + # Date range selection |
| 91 | + date_range = st.date_input( |
| 92 | + "Select Date Range:", |
| 93 | + [min_date.date(), max_date.date()], |
| 94 | + min_value=min_date.date(), |
| 95 | + max_value=max_date.date(), |
| 96 | + key='weekly_date_range' |
| 97 | + ) |
| 98 | + |
| 99 | + if isinstance(date_range, tuple) and len(date_range) == 2: |
| 100 | + start_date, end_date = date_range |
| 101 | + start_date = pd.to_datetime(start_date) |
| 102 | + end_date = pd.to_datetime(end_date) |
| 103 | + |
| 104 | + # Filter data based on selected date range |
| 105 | + df_filter = weekly_agg[(weekly_agg['WEEK_START'] >= start_date) & (weekly_agg['WEEK_START'] <= end_date)] |
| 106 | + |
| 107 | + st.line_chart(df_filter, x = 'WEEK_START', y = ['AVG_10Y', 'AVG_2Y'], |
| 108 | + height = 500, |
| 109 | + x_label= "Financial Period", |
| 110 | + y_label= "Yield") |
| 111 | + st.line_chart(df_filter, x = 'WEEK_START', y = ['AVG_10Y', 'MIN_10Y', 'MAX_10Y'], |
| 112 | + height = 500, |
| 113 | + x_label= "Financial Period", |
| 114 | + y_label= "Yield") |
| 115 | + st.line_chart(df_filter, x = 'WEEK_START', y = ['AVG_2Y', 'MIN_2Y', 'MAX_2Y'], |
| 116 | + height = 500, |
| 117 | + x_label= "Financial Period", |
| 118 | + y_label= "Yield") |
| 119 | + |
| 120 | + st.line_chart(df_filter, x = 'WEEK_START', y = ['AVG_10Y', 'AVG_2Y', |
| 121 | + 'MIN_10Y', 'MAX_10Y', |
| 122 | + 'MIN_2Y', 'MAX_2Y'], |
| 123 | + height = 500, |
| 124 | + x_label= "Financial Period", |
| 125 | + y_label= "Yield") |
| 126 | + |
| 127 | + data = df_filter[['WEEK_START', 'AVG_SPREAD']] |
| 128 | + |
| 129 | + data['Positive Change'] = data['AVG_SPREAD'].apply(lambda x: x if x >= 0 else None) |
| 130 | + data['Negative Change'] = data['AVG_SPREAD'].apply(lambda x: x if x < 0 else None) |
| 131 | + |
| 132 | + st.line_chart( |
| 133 | + data.set_index('WEEK_START')[['Positive Change', 'Negative Change']], |
| 134 | + use_container_width=True |
| 135 | + ) |
| 136 | + |
| 137 | + else: |
| 138 | + st.warning("Please select a valid date range.") |
| 139 | + |
| 140 | +def monthly_data_analytics(monthly_agg): |
| 141 | + st.subheader('Monthly Yield Spread Analytics') |
| 142 | + |
| 143 | + # Ensure MONTH_START is in datetime format |
| 144 | + monthly_agg['MONTH_START'] = pd.to_datetime(monthly_agg['MONTH_START']) |
| 145 | + |
| 146 | + # Get min and max date |
| 147 | + min_date = monthly_agg['MONTH_START'].min() |
| 148 | + max_date = monthly_agg['MONTH_START'].max() |
| 149 | + |
| 150 | + # Date range selection |
| 151 | + date_range = st.date_input( |
| 152 | + "Select Date Range:", |
| 153 | + [min_date.date(), max_date.date()], |
| 154 | + min_value=min_date.date(), |
| 155 | + max_value=max_date.date(), |
| 156 | + key='monthly_date_range' |
| 157 | + ) |
| 158 | + |
| 159 | + if isinstance(date_range, tuple) and len(date_range) == 2: |
| 160 | + start_date, end_date = date_range |
| 161 | + start_date = pd.to_datetime(start_date) |
| 162 | + end_date = pd.to_datetime(end_date) |
| 163 | + |
| 164 | + # Filter data based on selected date range |
| 165 | + df_filter = monthly_agg[(monthly_agg['MONTH_START'] >= start_date) & (monthly_agg['MONTH_START'] <= end_date)] |
| 166 | + |
| 167 | + st.line_chart(df_filter, x = 'MONTH_START', y = ['AVG_10Y', 'AVG_2Y'], |
| 168 | + height = 500, |
| 169 | + x_label= "Financial Period", |
| 170 | + y_label= "Yield") |
| 171 | + st.line_chart(df_filter, x = 'MONTH_START', y = ['AVG_10Y', 'MIN_10Y', 'MAX_10Y'], |
| 172 | + height = 500, |
| 173 | + x_label= "Financial Period", |
| 174 | + y_label= "Yield") |
| 175 | + st.line_chart(df_filter, x = 'MONTH_START', y = ['AVG_2Y', 'MIN_2Y', 'MAX_2Y'], |
| 176 | + height = 500, |
| 177 | + x_label= "Financial Period", |
| 178 | + y_label= "Yield") |
| 179 | + |
| 180 | + st.line_chart(df_filter, x = 'MONTH_START', y = ['AVG_10Y', 'AVG_2Y', |
| 181 | + 'MIN_10Y', 'MAX_10Y', |
| 182 | + 'MIN_2Y', 'MAX_2Y'], |
| 183 | + height = 500, |
| 184 | + x_label= "Financial Period", |
| 185 | + y_label= "Yield") |
| 186 | + |
| 187 | + data = df_filter[['MONTH_START', 'AVG_SPREAD']] |
| 188 | + |
| 189 | + data['Positive Change'] = data['AVG_SPREAD'].apply(lambda x: x if x >= 0 else None) |
| 190 | + data['Negative Change'] = data['AVG_SPREAD'].apply(lambda x: x if x < 0 else None) |
| 191 | + |
| 192 | + st.line_chart( |
| 193 | + data.set_index('MONTH_START')[['Positive Change', 'Negative Change']], |
| 194 | + use_container_width=True |
| 195 | + ) |
| 196 | + |
| 197 | + else: |
| 198 | + st.warning("Please select a valid date range.") |
| 199 | + |
| 200 | + |
| 201 | +def main(): |
| 202 | + # Set the title of the app |
| 203 | + st.title("FRED Yield Curve Analysis") |
| 204 | + st.header("Analysis of the Yield Curve Spread between 10Y and 2Y Treasury Bonds") |
| 205 | + |
| 206 | + # Establish Snowflake session |
| 207 | + conn = create_snowflake_connection() |
| 208 | + |
| 209 | + # Load data |
| 210 | + daily_agg, weekly_agg, monthly_agg = load_data(conn) |
| 211 | + |
| 212 | + # Select period |
| 213 | + period = st.selectbox("Select Period", ["DAILY", "WEEKLY", "MONTHLY"]) |
| 214 | + |
| 215 | + if period == "DAILY": |
| 216 | + daily_data_analytics(daily_agg) |
| 217 | + elif period == "WEEKLY": |
| 218 | + weekly_data_analytics(weekly_agg) |
| 219 | + elif period == "MONTHLY": |
| 220 | + monthly_data_analytics(monthly_agg) |
| 221 | + |
| 222 | +if __name__ == "__main__": |
| 223 | +# Set page configuration |
| 224 | + st.set_page_config( |
| 225 | + page_title="FRED - Snowflake Data Pipeline", # Name of the app |
| 226 | + layout="wide", # Layout: "centered" or "wide" |
| 227 | + initial_sidebar_state="expanded" # Sidebar: "expanded" or "collapsed" |
| 228 | + ) |
| 229 | + main() |
| 230 | + |
0 commit comments