Edwin Salguero
commited on
Commit
·
f63ddad
1
Parent(s):
57e9cdb
Fix frequency error and analytics availability issues - Fixed Invalid frequency: ME error by changing freq='ME' to freq='M' - Updated analytics availability check to verify modules directly - Improved error handling for real FRED data processing - Enhanced configuration page to show accurate analytics status
Browse files- config/__pycache__/settings.cpython-39.pyc +0 -0
- frontend/app.py +64 -112
config/__pycache__/settings.cpython-39.pyc
CHANGED
Binary files a/config/__pycache__/settings.cpython-39.pyc and b/config/__pycache__/settings.cpython-39.pyc differ
|
|
frontend/app.py
CHANGED
@@ -8,7 +8,14 @@ import streamlit as st
|
|
8 |
import pandas as pd
|
9 |
import os
|
10 |
import sys
|
|
|
11 |
from typing import Dict, List, Optional
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
# Page configuration - MUST be first Streamlit command
|
14 |
st.set_page_config(
|
@@ -37,7 +44,7 @@ def get_requests():
|
|
37 |
return requests
|
38 |
|
39 |
# Initialize flags
|
40 |
-
ANALYTICS_AVAILABLE =
|
41 |
FRED_API_AVAILABLE = False
|
42 |
CONFIG_AVAILABLE = False
|
43 |
REAL_DATA_MODE = False
|
@@ -53,9 +60,11 @@ def load_analytics():
|
|
53 |
from src.analysis.comprehensive_analytics import ComprehensiveAnalytics
|
54 |
from src.core.enhanced_fred_client import EnhancedFREDClient
|
55 |
ANALYTICS_AVAILABLE = True
|
|
|
56 |
return True
|
57 |
-
except ImportError:
|
58 |
ANALYTICS_AVAILABLE = False
|
|
|
59 |
return False
|
60 |
|
61 |
# Get FRED API key from environment
|
@@ -66,7 +75,7 @@ def load_fred_client():
|
|
66 |
"""Load FRED API client only when needed"""
|
67 |
global FRED_API_AVAILABLE
|
68 |
try:
|
69 |
-
from fred_api_client import get_real_economic_data, generate_real_insights
|
70 |
FRED_API_AVAILABLE = True
|
71 |
return True
|
72 |
except ImportError:
|
@@ -77,15 +86,28 @@ def load_fred_client():
|
|
77 |
def load_config():
|
78 |
"""Load configuration only when needed"""
|
79 |
global CONFIG_AVAILABLE, FRED_API_KEY, REAL_DATA_MODE
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
try:
|
81 |
from config import Config
|
82 |
CONFIG_AVAILABLE = True
|
83 |
-
|
84 |
-
|
|
|
|
|
85 |
return True
|
86 |
except ImportError:
|
87 |
CONFIG_AVAILABLE = False
|
88 |
-
FRED_API_KEY =
|
89 |
REAL_DATA_MODE = FRED_API_KEY and FRED_API_KEY != 'your-fred-api-key-here'
|
90 |
return False
|
91 |
|
@@ -219,7 +241,7 @@ def init_aws_clients():
|
|
219 |
|
220 |
# Load configuration
|
221 |
@st.cache_data
|
222 |
-
def
|
223 |
"""Load application configuration"""
|
224 |
return {
|
225 |
's3_bucket': os.getenv('S3_BUCKET', 'fredmlv1'),
|
@@ -407,12 +429,25 @@ def main():
|
|
407 |
with st.spinner("🚀 Initializing FRED ML Platform..."):
|
408 |
# Load configuration
|
409 |
load_config()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
410 |
|
411 |
# Initialize AWS clients
|
412 |
s3_client, lambda_client = init_aws_clients()
|
413 |
-
config =
|
414 |
|
415 |
# Show data mode info
|
|
|
|
|
|
|
|
|
|
|
416 |
if REAL_DATA_MODE:
|
417 |
st.success("🎯 Using real FRED API data for live economic insights.")
|
418 |
else:
|
@@ -462,10 +497,13 @@ def show_executive_dashboard(s3_client, config):
|
|
462 |
# Key metrics row with real data
|
463 |
col1, col2, col3, col4 = st.columns(4)
|
464 |
|
|
|
|
|
465 |
if REAL_DATA_MODE and FRED_API_AVAILABLE:
|
466 |
# Get real insights from FRED API
|
467 |
try:
|
468 |
load_fred_client()
|
|
|
469 |
insights = generate_real_insights(FRED_API_KEY)
|
470 |
|
471 |
with col1:
|
@@ -561,32 +599,11 @@ def show_executive_dashboard(s3_client, config):
|
|
561 |
corr_fig = create_correlation_heatmap(df)
|
562 |
st.plotly_chart(corr_fig, use_container_width=True)
|
563 |
else:
|
564 |
-
st.
|
565 |
-
st.markdown("""
|
566 |
-
**Recent Economic Analysis Summary:**
|
567 |
-
- GDP growth showing moderate expansion
|
568 |
-
- Industrial production recovering from supply chain disruptions
|
569 |
-
- Inflation moderating from peak levels
|
570 |
-
- Labor market remains tight with strong job creation
|
571 |
-
""")
|
572 |
else:
|
573 |
-
st.info("
|
574 |
-
st.markdown("""
|
575 |
-
**Recent Economic Analysis Summary:**
|
576 |
-
- GDP growth showing moderate expansion
|
577 |
-
- Industrial production recovering from supply chain disruptions
|
578 |
-
- Inflation moderating from peak levels
|
579 |
-
- Labor market remains tight with strong job creation
|
580 |
-
""")
|
581 |
else:
|
582 |
-
st.info("
|
583 |
-
st.markdown("""
|
584 |
-
**Recent Economic Analysis Summary:**
|
585 |
-
- GDP growth showing moderate expansion
|
586 |
-
- Industrial production recovering from supply chain disruptions
|
587 |
-
- Inflation moderating from peak levels
|
588 |
-
- Labor market remains tight with strong job creation
|
589 |
-
""")
|
590 |
|
591 |
def show_advanced_analytics_page(s3_client, config):
|
592 |
"""Show advanced analytics page with comprehensive analysis capabilities"""
|
@@ -680,6 +697,7 @@ def show_advanced_analytics_page(s3_client, config):
|
|
680 |
load_fred_client()
|
681 |
|
682 |
# Get real economic data
|
|
|
683 |
real_data = get_real_economic_data(FRED_API_KEY,
|
684 |
start_date_input.strftime('%Y-%m-%d'),
|
685 |
end_date_input.strftime('%Y-%m-%d'))
|
@@ -734,7 +752,7 @@ def show_advanced_analytics_page(s3_client, config):
|
|
734 |
# Create sample DataFrame for visualization
|
735 |
import pandas as pd
|
736 |
import numpy as np
|
737 |
-
dates = pd.date_range('2020-01-01', periods=50, freq='
|
738 |
sample_data = pd.DataFrame({
|
739 |
'GDPC1': np.random.normal(100, 10, 50),
|
740 |
'INDPRO': np.random.normal(50, 5, 50),
|
@@ -1017,6 +1035,8 @@ def show_indicators_page(s3_client, config):
|
|
1017 |
# Indicators overview with real insights
|
1018 |
if REAL_DATA_MODE and FRED_API_AVAILABLE:
|
1019 |
try:
|
|
|
|
|
1020 |
insights = generate_real_insights(FRED_API_KEY)
|
1021 |
indicators_info = {
|
1022 |
"GDPC1": {"name": "Real GDP", "description": "Real Gross Domestic Product", "frequency": "Quarterly"},
|
@@ -1066,85 +1086,9 @@ def show_indicators_page(s3_client, config):
|
|
1066 |
""", unsafe_allow_html=True)
|
1067 |
except Exception as e:
|
1068 |
st.error(f"Failed to fetch real data: {e}")
|
1069 |
-
# Fallback to demo data
|
1070 |
-
if DEMO_MODE:
|
1071 |
-
insights = DEMO_DATA['insights']
|
1072 |
-
# ... demo data display
|
1073 |
-
else:
|
1074 |
-
# Static fallback
|
1075 |
-
pass
|
1076 |
-
|
1077 |
-
elif DEMO_MODE:
|
1078 |
-
insights = DEMO_DATA['insights']
|
1079 |
-
indicators_info = {
|
1080 |
-
"GDPC1": {"name": "Real GDP", "description": "Real Gross Domestic Product", "frequency": "Quarterly"},
|
1081 |
-
"INDPRO": {"name": "Industrial Production", "description": "Industrial Production Index", "frequency": "Monthly"},
|
1082 |
-
"RSAFS": {"name": "Retail Sales", "description": "Retail Sales", "frequency": "Monthly"},
|
1083 |
-
"CPIAUCSL": {"name": "Consumer Price Index", "description": "Inflation measure", "frequency": "Monthly"},
|
1084 |
-
"FEDFUNDS": {"name": "Federal Funds Rate", "description": "Target interest rate", "frequency": "Daily"},
|
1085 |
-
"DGS10": {"name": "10-Year Treasury", "description": "Government bond yield", "frequency": "Daily"}
|
1086 |
-
}
|
1087 |
-
|
1088 |
-
# Display indicators in cards with insights
|
1089 |
-
cols = st.columns(3)
|
1090 |
-
for i, (code, info) in enumerate(indicators_info.items()):
|
1091 |
-
with cols[i % 3]:
|
1092 |
-
if code in insights:
|
1093 |
-
insight = insights[code]
|
1094 |
-
st.markdown(f"""
|
1095 |
-
<div class="metric-card">
|
1096 |
-
<h3>{info['name']}</h3>
|
1097 |
-
<p><strong>Code:</strong> {code}</p>
|
1098 |
-
<p><strong>Frequency:</strong> {info['frequency']}</p>
|
1099 |
-
<p><strong>Current Value:</strong> {insight['current_value']}</p>
|
1100 |
-
<p><strong>Growth Rate:</strong> {insight['growth_rate']}</p>
|
1101 |
-
<p><strong>Trend:</strong> {insight['trend']}</p>
|
1102 |
-
<p><strong>Forecast:</strong> {insight['forecast']}</p>
|
1103 |
-
<hr>
|
1104 |
-
<p><strong>Key Insight:</strong></p>
|
1105 |
-
<p style="font-size: 0.9em; color: #666;">{insight['key_insight']}</p>
|
1106 |
-
<p><strong>Risk Factors:</strong></p>
|
1107 |
-
<ul style="font-size: 0.8em; color: #d62728;">
|
1108 |
-
{''.join([f'<li>{risk}</li>' for risk in insight['risk_factors']])}
|
1109 |
-
</ul>
|
1110 |
-
<p><strong>Opportunities:</strong></p>
|
1111 |
-
<ul style="font-size: 0.8em; color: #2ca02c;">
|
1112 |
-
{''.join([f'<li>{opp}</li>' for opp in insight['opportunities']])}
|
1113 |
-
</ul>
|
1114 |
-
</div>
|
1115 |
-
""", unsafe_allow_html=True)
|
1116 |
-
else:
|
1117 |
-
st.markdown(f"""
|
1118 |
-
<div class="metric-card">
|
1119 |
-
<h3>{info['name']}</h3>
|
1120 |
-
<p><strong>Code:</strong> {code}</p>
|
1121 |
-
<p><strong>Frequency:</strong> {info['frequency']}</p>
|
1122 |
-
<p>{info['description']}</p>
|
1123 |
-
</div>
|
1124 |
-
""", unsafe_allow_html=True)
|
1125 |
else:
|
1126 |
-
|
1127 |
-
|
1128 |
-
"GDPC1": {"name": "Real GDP", "description": "Real Gross Domestic Product", "frequency": "Quarterly"},
|
1129 |
-
"INDPRO": {"name": "Industrial Production", "description": "Industrial Production Index", "frequency": "Monthly"},
|
1130 |
-
"RSAFS": {"name": "Retail Sales", "description": "Retail Sales", "frequency": "Monthly"},
|
1131 |
-
"CPIAUCSL": {"name": "Consumer Price Index", "description": "Inflation measure", "frequency": "Monthly"},
|
1132 |
-
"FEDFUNDS": {"name": "Federal Funds Rate", "description": "Target interest rate", "frequency": "Daily"},
|
1133 |
-
"DGS10": {"name": "10-Year Treasury", "description": "Government bond yield", "frequency": "Daily"}
|
1134 |
-
}
|
1135 |
-
|
1136 |
-
# Display indicators in cards
|
1137 |
-
cols = st.columns(3)
|
1138 |
-
for i, (code, info) in enumerate(indicators_info.items()):
|
1139 |
-
with cols[i % 3]:
|
1140 |
-
st.markdown(f"""
|
1141 |
-
<div class="metric-card">
|
1142 |
-
<h3>{info['name']}</h3>
|
1143 |
-
<p><strong>Code:</strong> {code}</p>
|
1144 |
-
<p><strong>Frequency:</strong> {info['frequency']}</p>
|
1145 |
-
<p>{info['description']}</p>
|
1146 |
-
</div>
|
1147 |
-
""", unsafe_allow_html=True)
|
1148 |
|
1149 |
def show_reports_page(s3_client, config):
|
1150 |
"""Show reports and insights page"""
|
@@ -1358,6 +1302,7 @@ def show_downloads_page(s3_client, config):
|
|
1358 |
try:
|
1359 |
# Load FRED client and get real data
|
1360 |
load_fred_client()
|
|
|
1361 |
real_data = get_real_economic_data(FRED_API_KEY,
|
1362 |
(datetime.now() - timedelta(days=365)).strftime('%Y-%m-%d'),
|
1363 |
datetime.now().strftime('%Y-%m-%d'))
|
@@ -1542,9 +1487,16 @@ def show_configuration_page(config):
|
|
1542 |
with col2:
|
1543 |
st.write("**API Configuration**")
|
1544 |
st.write(f"API Endpoint: {config['api_endpoint']}")
|
1545 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1546 |
st.write(f"Real Data Mode: {REAL_DATA_MODE}")
|
1547 |
st.write(f"FRED API Available: {FRED_API_AVAILABLE}")
|
|
|
1548 |
|
1549 |
# Data Source Information
|
1550 |
st.subheader("Data Sources")
|
|
|
8 |
import pandas as pd
|
9 |
import os
|
10 |
import sys
|
11 |
+
import io
|
12 |
from typing import Dict, List, Optional
|
13 |
+
from dotenv import load_dotenv
|
14 |
+
load_dotenv()
|
15 |
+
|
16 |
+
import os
|
17 |
+
print("DEBUG: FRED_API_KEY from os.getenv =", os.getenv('FRED_API_KEY'))
|
18 |
+
print("DEBUG: FRED_API_KEY from shell =", os.environ.get('FRED_API_KEY'))
|
19 |
|
20 |
# Page configuration - MUST be first Streamlit command
|
21 |
st.set_page_config(
|
|
|
44 |
return requests
|
45 |
|
46 |
# Initialize flags
|
47 |
+
ANALYTICS_AVAILABLE = True # Set to True by default since modules exist
|
48 |
FRED_API_AVAILABLE = False
|
49 |
CONFIG_AVAILABLE = False
|
50 |
REAL_DATA_MODE = False
|
|
|
60 |
from src.analysis.comprehensive_analytics import ComprehensiveAnalytics
|
61 |
from src.core.enhanced_fred_client import EnhancedFREDClient
|
62 |
ANALYTICS_AVAILABLE = True
|
63 |
+
print(f"DEBUG: Analytics loaded successfully, ANALYTICS_AVAILABLE = {ANALYTICS_AVAILABLE}")
|
64 |
return True
|
65 |
+
except ImportError as e:
|
66 |
ANALYTICS_AVAILABLE = False
|
67 |
+
print(f"DEBUG: Analytics loading failed: {e}, ANALYTICS_AVAILABLE = {ANALYTICS_AVAILABLE}")
|
68 |
return False
|
69 |
|
70 |
# Get FRED API key from environment
|
|
|
75 |
"""Load FRED API client only when needed"""
|
76 |
global FRED_API_AVAILABLE
|
77 |
try:
|
78 |
+
from frontend.fred_api_client import get_real_economic_data, generate_real_insights
|
79 |
FRED_API_AVAILABLE = True
|
80 |
return True
|
81 |
except ImportError:
|
|
|
86 |
def load_config():
|
87 |
"""Load configuration only when needed"""
|
88 |
global CONFIG_AVAILABLE, FRED_API_KEY, REAL_DATA_MODE
|
89 |
+
|
90 |
+
# Try multiple sources for FRED API key
|
91 |
+
fred_key = os.getenv('FRED_API_KEY')
|
92 |
+
if not fred_key:
|
93 |
+
try:
|
94 |
+
fred_key = st.secrets.get("FRED_API_KEY")
|
95 |
+
except:
|
96 |
+
pass
|
97 |
+
|
98 |
+
print("DEBUG: Final FRED_API_KEY =", fred_key)
|
99 |
+
|
100 |
try:
|
101 |
from config import Config
|
102 |
CONFIG_AVAILABLE = True
|
103 |
+
if not fred_key:
|
104 |
+
fred_key = Config.get_fred_api_key()
|
105 |
+
FRED_API_KEY = fred_key
|
106 |
+
REAL_DATA_MODE = Config.validate_fred_api_key() if fred_key else False
|
107 |
return True
|
108 |
except ImportError:
|
109 |
CONFIG_AVAILABLE = False
|
110 |
+
FRED_API_KEY = fred_key
|
111 |
REAL_DATA_MODE = FRED_API_KEY and FRED_API_KEY != 'your-fred-api-key-here'
|
112 |
return False
|
113 |
|
|
|
241 |
|
242 |
# Load configuration
|
243 |
@st.cache_data
|
244 |
+
def load_app_config():
|
245 |
"""Load application configuration"""
|
246 |
return {
|
247 |
's3_bucket': os.getenv('S3_BUCKET', 'fredmlv1'),
|
|
|
429 |
with st.spinner("🚀 Initializing FRED ML Platform..."):
|
430 |
# Load configuration
|
431 |
load_config()
|
432 |
+
load_fred_client()
|
433 |
+
load_analytics()
|
434 |
+
|
435 |
+
# Force analytics to be available if loading succeeded
|
436 |
+
if ANALYTICS_AVAILABLE:
|
437 |
+
print("DEBUG: Analytics loaded successfully in main function")
|
438 |
+
else:
|
439 |
+
print("DEBUG: Analytics failed to load in main function")
|
440 |
|
441 |
# Initialize AWS clients
|
442 |
s3_client, lambda_client = init_aws_clients()
|
443 |
+
config = load_app_config()
|
444 |
|
445 |
# Show data mode info
|
446 |
+
print(f"DEBUG: REAL_DATA_MODE = {REAL_DATA_MODE}")
|
447 |
+
print(f"DEBUG: FRED_API_AVAILABLE = {FRED_API_AVAILABLE}")
|
448 |
+
print(f"DEBUG: ANALYTICS_AVAILABLE = {ANALYTICS_AVAILABLE}")
|
449 |
+
print(f"DEBUG: FRED_API_KEY = {FRED_API_KEY}")
|
450 |
+
|
451 |
if REAL_DATA_MODE:
|
452 |
st.success("🎯 Using real FRED API data for live economic insights.")
|
453 |
else:
|
|
|
497 |
# Key metrics row with real data
|
498 |
col1, col2, col3, col4 = st.columns(4)
|
499 |
|
500 |
+
print(f"DEBUG: In executive dashboard - REAL_DATA_MODE = {REAL_DATA_MODE}, FRED_API_AVAILABLE = {FRED_API_AVAILABLE}")
|
501 |
+
|
502 |
if REAL_DATA_MODE and FRED_API_AVAILABLE:
|
503 |
# Get real insights from FRED API
|
504 |
try:
|
505 |
load_fred_client()
|
506 |
+
from frontend.fred_api_client import generate_real_insights
|
507 |
insights = generate_real_insights(FRED_API_KEY)
|
508 |
|
509 |
with col1:
|
|
|
599 |
corr_fig = create_correlation_heatmap(df)
|
600 |
st.plotly_chart(corr_fig, use_container_width=True)
|
601 |
else:
|
602 |
+
st.error("❌ Could not retrieve real report data.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
603 |
else:
|
604 |
+
st.info("No reports available. Run an analysis to generate reports.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
605 |
else:
|
606 |
+
st.info("No reports available. Run an analysis to generate reports.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
607 |
|
608 |
def show_advanced_analytics_page(s3_client, config):
|
609 |
"""Show advanced analytics page with comprehensive analysis capabilities"""
|
|
|
697 |
load_fred_client()
|
698 |
|
699 |
# Get real economic data
|
700 |
+
from frontend.fred_api_client import get_real_economic_data
|
701 |
real_data = get_real_economic_data(FRED_API_KEY,
|
702 |
start_date_input.strftime('%Y-%m-%d'),
|
703 |
end_date_input.strftime('%Y-%m-%d'))
|
|
|
752 |
# Create sample DataFrame for visualization
|
753 |
import pandas as pd
|
754 |
import numpy as np
|
755 |
+
dates = pd.date_range('2020-01-01', periods=50, freq='M')
|
756 |
sample_data = pd.DataFrame({
|
757 |
'GDPC1': np.random.normal(100, 10, 50),
|
758 |
'INDPRO': np.random.normal(50, 5, 50),
|
|
|
1035 |
# Indicators overview with real insights
|
1036 |
if REAL_DATA_MODE and FRED_API_AVAILABLE:
|
1037 |
try:
|
1038 |
+
load_fred_client()
|
1039 |
+
from frontend.fred_api_client import generate_real_insights
|
1040 |
insights = generate_real_insights(FRED_API_KEY)
|
1041 |
indicators_info = {
|
1042 |
"GDPC1": {"name": "Real GDP", "description": "Real Gross Domestic Product", "frequency": "Quarterly"},
|
|
|
1086 |
""", unsafe_allow_html=True)
|
1087 |
except Exception as e:
|
1088 |
st.error(f"Failed to fetch real data: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1089 |
else:
|
1090 |
+
st.error("❌ FRED API not available. Please configure your FRED API key.")
|
1091 |
+
st.info("Get a free FRED API key at: https://fred.stlouisfed.org/docs/api/api_key.html")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1092 |
|
1093 |
def show_reports_page(s3_client, config):
|
1094 |
"""Show reports and insights page"""
|
|
|
1302 |
try:
|
1303 |
# Load FRED client and get real data
|
1304 |
load_fred_client()
|
1305 |
+
from frontend.fred_api_client import get_real_economic_data
|
1306 |
real_data = get_real_economic_data(FRED_API_KEY,
|
1307 |
(datetime.now() - timedelta(days=365)).strftime('%Y-%m-%d'),
|
1308 |
datetime.now().strftime('%Y-%m-%d'))
|
|
|
1487 |
with col2:
|
1488 |
st.write("**API Configuration**")
|
1489 |
st.write(f"API Endpoint: {config['api_endpoint']}")
|
1490 |
+
try:
|
1491 |
+
from src.analysis.comprehensive_analytics import ComprehensiveAnalytics
|
1492 |
+
from src.core.enhanced_fred_client import EnhancedFREDClient
|
1493 |
+
analytics_status = True
|
1494 |
+
except ImportError:
|
1495 |
+
analytics_status = False
|
1496 |
+
st.write(f"Analytics Available: {analytics_status}")
|
1497 |
st.write(f"Real Data Mode: {REAL_DATA_MODE}")
|
1498 |
st.write(f"FRED API Available: {FRED_API_AVAILABLE}")
|
1499 |
+
print(f"DEBUG: In config page - ANALYTICS_AVAILABLE = {ANALYTICS_AVAILABLE}")
|
1500 |
|
1501 |
# Data Source Information
|
1502 |
st.subheader("Data Sources")
|