gkippili commited on
Commit
fc69d52
·
verified ·
1 Parent(s): d5be8a7

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +553 -0
app.py ADDED
@@ -0,0 +1,553 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import yfinance as yf
4
+ import plotly.express as px
5
+ import plotly.graph_objects as go
6
+ from datetime import datetime, timedelta
7
+ import requests
8
+ from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager
9
+ import json
10
+
11
+ # Set Streamlit page configuration
12
+ st.set_page_config(
13
+ page_title="AI-Powered Financial Advisor",
14
+ page_icon="💰",
15
+ layout="wide",
16
+ )
17
+
18
+ # Custom CSS styling
19
+ st.markdown("""
20
+ <style>
21
+ .stTextInput > label {
22
+ font-weight: 500;
23
+ }
24
+ .stSelectbox > label {
25
+ font-weight: 500;
26
+ }
27
+ .stNumberInput > label {
28
+ font-weight: 500;
29
+ }
30
+ .stButton > button {
31
+ background-color: #4CAF50;
32
+ color: white;
33
+ font-weight: bold;
34
+ }
35
+ .result-box {
36
+ background-color: #f5f5f5;
37
+ padding: 20px;
38
+ border-radius: 10px;
39
+ margin: 20px 0;
40
+ border: 1px solid #ddd;
41
+ }
42
+ .metric-card {
43
+ background-color: white;
44
+ padding: 15px;
45
+ border-radius: 8px;
46
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
47
+ text-align: center;
48
+ margin-bottom: 15px;
49
+ }
50
+ .metric-value {
51
+ font-size: 24px;
52
+ font-weight: bold;
53
+ color: #1E88E5;
54
+ }
55
+ .metric-label {
56
+ font-size: 14px;
57
+ color: #757575;
58
+ }
59
+ </style>
60
+ """, unsafe_allow_html=True)
61
+
62
+ # Currency and interest rate data by country
63
+ country_data = {
64
+ "India": {
65
+ "currency": "₹",
66
+ "currency_code": "INR",
67
+ "base_interest_rate": 6.5, # Reserve Bank of India repo rate
68
+ "tax_brackets": [
69
+ {"limit": 250000, "rate": 0},
70
+ {"limit": 500000, "rate": 5},
71
+ {"limit": 1000000, "rate": 20},
72
+ {"limit": float('inf'), "rate": 30}
73
+ ],
74
+ "major_indices": ["^NSEI", "^BSESN"], # Nifty 50, Sensex
75
+ "popular_funds": ["ICICRED.NS", "HDFCAMC.NS", "KOTAKBANK.NS"],
76
+ "safe_instruments": {"Fixed Deposit": 5.5, "PPF": 7.1, "Government Bonds": 7.0}
77
+ },
78
+ "USA": {
79
+ "currency": "$",
80
+ "currency_code": "USD",
81
+ "base_interest_rate": 5.5, # Federal Reserve rate
82
+ "tax_brackets": [
83
+ {"limit": 11000, "rate": 10},
84
+ {"limit": 44725, "rate": 12},
85
+ {"limit": 95375, "rate": 22},
86
+ {"limit": 182100, "rate": 24},
87
+ {"limit": 231250, "rate": 32},
88
+ {"limit": 578125, "rate": 35},
89
+ {"limit": float('inf'), "rate": 37}
90
+ ],
91
+ "major_indices": ["^GSPC", "^DJI", "^IXIC"], # S&P 500, Dow Jones, Nasdaq
92
+ "popular_funds": ["SPY", "VOO", "QQQ"],
93
+ "safe_instruments": {"Treasury Bonds": 4.2, "CD": 4.0, "High-Yield Savings": 3.8}
94
+ },
95
+ "UK": {
96
+ "currency": "£",
97
+ "currency_code": "GBP",
98
+ "base_interest_rate": 5.25, # Bank of England rate
99
+ "tax_brackets": [
100
+ {"limit": 12570, "rate": 0}, # Personal Allowance
101
+ {"limit": 50270, "rate": 20}, # Basic rate
102
+ {"limit": 125140, "rate": 40}, # Higher rate
103
+ {"limit": float('inf'), "rate": 45} # Additional rate
104
+ ],
105
+ "major_indices": ["^FTSE"], # FTSE 100
106
+ "popular_funds": ["CUKX.L", "MIDD.L", "ISF.L"],
107
+ "safe_instruments": {"Premium Bonds": 4.65, "Fixed Rate Bonds": 4.8, "Cash ISA": 4.5}
108
+ }
109
+ }
110
+
111
+ # Function to fetch real-time currency exchange rates
112
+ @st.cache_data(ttl=3600) # Cache for 1 hour
113
+ def get_exchange_rates(base_currency):
114
+ try:
115
+ url = f"https://open.er-api.com/v6/latest/{base_currency}"
116
+ response = requests.get(url)
117
+ data = response.json()
118
+ if data["result"] == "success":
119
+ return data["rates"]
120
+ else:
121
+ return {"USD": 1.0, "INR": 82.5, "GBP": 0.79}
122
+ except:
123
+ # Default fallback rates
124
+ return {"USD": 1.0, "INR": 82.5, "GBP": 0.79}
125
+
126
+ # Function to fetch market index data
127
+ @st.cache_data(ttl=3600) # Cache for 1 hour
128
+ def get_market_indices(ticker_symbols):
129
+ end_date = datetime.now()
130
+ start_date = end_date - timedelta(days=365)
131
+
132
+ data = {}
133
+ for ticker in ticker_symbols:
134
+ try:
135
+ ticker_data = yf.download(ticker, start=start_date, end=end_date)
136
+ if not ticker_data.empty:
137
+ data[ticker] = ticker_data
138
+ except:
139
+ pass
140
+
141
+ return data
142
+
143
+ # Function to get real-time inflation data
144
+ @st.cache_data(ttl=86400) # Cache for 1 day
145
+ def get_inflation_rates():
146
+ # This would ideally be from an API, but using static recent data for demo
147
+ return {
148
+ "India": 5.1,
149
+ "USA": 3.3,
150
+ "UK": 3.2
151
+ }
152
+
153
+ # Function to convert currency
154
+ def convert_currency(amount, from_currency, to_currency):
155
+ if from_currency == to_currency:
156
+ return amount
157
+
158
+ rates = get_exchange_rates(from_currency)
159
+ if to_currency in rates:
160
+ return amount * rates[to_currency]
161
+ return amount # Fallback to original amount if conversion fails
162
+
163
+ # Streamlit UI components
164
+ st.title("AI-Powered Financial Advisor")
165
+
166
+ # Sidebar for real-time market information
167
+ with st.sidebar:
168
+ st.header("Market Overview")
169
+
170
+ # Get inflation rates
171
+ inflation_rates = get_inflation_rates()
172
+
173
+ # Display inflation rates
174
+ st.subheader("Current Inflation Rates")
175
+ for country, rate in inflation_rates.items():
176
+ st.metric(country, f"{rate}%")
177
+
178
+ st.markdown("---")
179
+
180
+ # Display current date and time
181
+ st.write(f"Last updated: {datetime.now().strftime('%Y-%m-%d %H:%M')}")
182
+
183
+ # Main input form
184
+ col1, col2 = st.columns(2)
185
+
186
+ with col1:
187
+ name = st.text_input("Full Name")
188
+ location = st.selectbox("Country", options=["India", "USA", "UK"])
189
+ age = st.number_input("Age", min_value=18, max_value=100)
190
+ marital_status = st.selectbox("Marital Status", ["Single", "Married"])
191
+
192
+ # Get currency symbol based on selected country
193
+ currency_symbol = country_data[location]["currency"]
194
+ currency_code = country_data[location]["currency_code"]
195
+
196
+ with col2:
197
+ assets = st.multiselect("Assets",
198
+ ["Car", "House", "Bank Balance", "Stocks", "Mutual Funds", "Real Estate", "Gold", "Other"])
199
+ asset_values = {asset: st.number_input(f"{asset} Value ({currency_symbol})", min_value=0) for asset in assets}
200
+
201
+ debts = st.multiselect("Debts",
202
+ ["Education Loan", "Home Loan", "Personal Loan", "Credit Card", "Gold Loan", "Other"])
203
+ debt_values = {debt: st.number_input(f"{debt} Amount ({currency_symbol})", min_value=0) for debt in debts}
204
+
205
+ monthly_savings = st.number_input(f"Monthly Savings ({currency_symbol})", min_value=0)
206
+ target_amount = st.number_input(f"Target Amount ({currency_symbol})", min_value=0)
207
+ target_years = st.number_input("Target Time (Years)", min_value=1, max_value=50)
208
+
209
+ # Market data fetching based on selected country
210
+ market_data_loaded = False
211
+ if location:
212
+ try:
213
+ with st.expander("View Current Market Data"):
214
+ st.subheader(f"Market Indices - {location}")
215
+ indices_data = get_market_indices(country_data[location]["major_indices"])
216
+
217
+ if indices_data:
218
+ for ticker, data in indices_data.items():
219
+ # Calculate percentage change
220
+ if not data.empty:
221
+ current = data['Close'].iloc[-1]
222
+ previous = data['Close'].iloc[-2]
223
+ change_pct = (current - previous) / previous * 100
224
+
225
+ # Display the index name and its current value
226
+ index_name = {
227
+ "^NSEI": "Nifty 50", "^BSESN": "Sensex",
228
+ "^GSPC": "S&P 500", "^DJI": "Dow Jones", "^IXIC": "Nasdaq",
229
+ "^FTSE": "FTSE 100"
230
+ }.get(ticker, ticker)
231
+
232
+ st.metric(
233
+ index_name,
234
+ f"{current:.2f}",
235
+ f"{change_pct:.2f}%",
236
+ delta_color="normal"
237
+ )
238
+
239
+ # Plot the index trend
240
+ fig = px.line(data, y='Close', title=f"{index_name} - Past Year")
241
+ st.plotly_chart(fig, use_container_width=True)
242
+ market_data_loaded = True
243
+ else:
244
+ market_data_loaded = False
245
+ except:
246
+ # Silently handle the exception without showing error to user
247
+ market_data_loaded = False
248
+
249
+ if st.button("Calculate"):
250
+ # Display a loading spinner
251
+ with st.spinner("Analyzing financial data and generating recommendations..."):
252
+ # Calculate total assets and debts
253
+ total_assets = sum(asset_values.values())
254
+ total_debts = sum(debt_values.values())
255
+ net_worth = total_assets - total_debts
256
+
257
+ # Dashboard Metrics
258
+ st.markdown('<div class="result-box">', unsafe_allow_html=True)
259
+
260
+ # Financial overview section
261
+ st.header("Financial Overview")
262
+
263
+ # Display key metrics
264
+ metric_cols = st.columns(4)
265
+ with metric_cols[0]:
266
+ st.markdown(f"""
267
+ <div class="metric-card">
268
+ <div class="metric-value">{currency_symbol}{net_worth:,.2f}</div>
269
+ <div class="metric-label">Net Worth</div>
270
+ </div>
271
+ """, unsafe_allow_html=True)
272
+
273
+ with metric_cols[1]:
274
+ debt_to_asset = 0 if total_assets == 0 else (total_debts / total_assets) * 100
275
+ st.markdown(f"""
276
+ <div class="metric-card">
277
+ <div class="metric-value">{debt_to_asset:.1f}%</div>
278
+ <div class="metric-label">Debt-to-Asset Ratio</div>
279
+ </div>
280
+ """, unsafe_allow_html=True)
281
+
282
+ with metric_cols[2]:
283
+ st.markdown(f"""
284
+ <div class="metric-card">
285
+ <div class="metric-value">{currency_symbol}{monthly_savings:,.2f}</div>
286
+ <div class="metric-label">Monthly Savings</div>
287
+ </div>
288
+ """, unsafe_allow_html=True)
289
+
290
+ with metric_cols[3]:
291
+ # FIX 2: Use the user-entered target_years value directly instead of calculating
292
+ st.markdown(f"""
293
+ <div class="metric-card">
294
+ <div class="metric-value">{target_years}</div>
295
+ <div class="metric-label">Years to Goal</div>
296
+ </div>
297
+ """, unsafe_allow_html=True)
298
+
299
+ # Net Worth Breakdown Chart
300
+ st.subheader("Net Worth Breakdown")
301
+
302
+ # FIX 1: Improve pie chart data preparation to properly show both assets and debts
303
+ if total_assets > 0 or total_debts > 0:
304
+ # Create two separate traces for a better visualization
305
+ fig = go.Figure()
306
+
307
+ # Group assets together (positive values)
308
+ asset_labels = []
309
+ asset_values_list = []
310
+ for asset, value in asset_values.items():
311
+ if value > 0:
312
+ asset_labels.append(asset)
313
+ asset_values_list.append(value)
314
+
315
+ # Group debts together (use absolute values for display)
316
+ debt_labels = []
317
+ debt_values_list = []
318
+ for debt, value in debt_values.items():
319
+ if value > 0:
320
+ debt_labels.append(debt)
321
+ debt_values_list.append(value) # Using positive values for better visualization
322
+
323
+ # Create combined labels and values for the pie chart
324
+ combined_labels = asset_labels + debt_labels
325
+ combined_values = asset_values_list + [-v for v in debt_values_list] # Make debt values negative
326
+
327
+ if combined_labels and combined_values:
328
+ # Use abs(val) for sizing the pie segments but keep colors based on sign
329
+ fig = go.Figure(data=[go.Pie(
330
+ labels=combined_labels,
331
+ values=[abs(val) for val in combined_values], # Use absolute values for segment size
332
+ hole=.4,
333
+ textinfo='label+percent',
334
+ marker=dict(colors=[
335
+ '#4CAF50' if val > 0 else '#F44336' for val in combined_values
336
+ ])
337
+ )])
338
+
339
+ # Add a color legend
340
+ fig.update_layout(
341
+ title_text="Assets and Debts",
342
+ legend_title="Items",
343
+ annotations=[
344
+ dict(text="Assets", x=0.85, y=1.1, showarrow=False, font=dict(color='#4CAF50', size=12)),
345
+ dict(text="Debts", x=0.95, y=1.1, showarrow=False, font=dict(color='#F44336', size=12))
346
+ ]
347
+ )
348
+ st.plotly_chart(fig, use_container_width=True)
349
+ else:
350
+ st.info("Please enter asset and debt values to see breakdown")
351
+
352
+ # Create AutoGen agents
353
+ financial_planner = AssistantAgent(
354
+ name="Financial_Planner",
355
+ llm_config={"model": "gpt-4o"},
356
+ system_message=f"""
357
+ You are a certified financial planner specializing in {location}-based financial planning.
358
+ Use the following real-time market data for your analysis:
359
+ - Current inflation rate in {location}: {inflation_rates.get(location, 5.0)}%
360
+ - Base interest rate: {country_data[location]['base_interest_rate']}%
361
+ - Safe investment returns: {json.dumps(country_data[location]['safe_instruments'])}
362
+ - Tax brackets: {json.dumps(country_data[location]['tax_brackets'])}
363
+
364
+ Your task is to:
365
+ 1. Calculate user's net worth and analyze financial health
366
+ 2. Assess feasibility of financial goals
367
+ 3. Provide detailed investment recommendations specific to {location}
368
+ """
369
+ )
370
+
371
+ market_analyst = AssistantAgent(
372
+ name="Market_Analyst",
373
+ llm_config={"model": "gpt-4o"},
374
+ system_message=f"""
375
+ You are a market analyst specializing in {location} financial markets.
376
+ Use the following real-time market data:
377
+ - Current inflation rate in {location}: {inflation_rates.get(location, 5.0)}%
378
+ - Popular market indices in {location}: {country_data[location]['major_indices']}
379
+ - Popular funds in {location}: {country_data[location]['popular_funds']}
380
+
381
+ Your task is to:
382
+ 1. Analyze current market conditions in {location}
383
+ 2. Recommend specific investment vehicles appropriate for the user's situation
384
+ 3. Provide a realistic forecast of expected returns in {location}'s market
385
+ """
386
+ )
387
+
388
+ tax_advisor = AssistantAgent(
389
+ name="Tax_Advisor",
390
+ llm_config={"model": "gpt-4o"},
391
+ system_message=f"""
392
+ You are a tax advisor specializing in {location} tax law.
393
+ Use the following real-time data:
394
+ - Tax brackets in {location}: {json.dumps(country_data[location]['tax_brackets'])}
395
+ - Available tax-saving instruments in {location}: {json.dumps(country_data[location]['safe_instruments'])}
396
+
397
+ Your task is to:
398
+ 1. Calculate potential tax liability based on income and assets
399
+ 2. Suggest specific tax-saving strategies available in {location}
400
+ 3. Recommend tax-efficient investment vehicles for the user's goals
401
+ """
402
+ )
403
+
404
+ user_proxy = UserProxyAgent(
405
+ name="User",
406
+ human_input_mode="NEVER",
407
+ system_message="You represent the user and relay their financial goals.",
408
+ code_execution_config={"use_docker": False}
409
+ )
410
+
411
+ # Group chat setup
412
+ group_chat = GroupChat(
413
+ agents=[user_proxy, financial_planner, market_analyst, tax_advisor],
414
+ messages=[],
415
+ max_round=10
416
+ )
417
+
418
+ manager = GroupChatManager(groupchat=group_chat, llm_config={"model": "gpt-4o"})
419
+
420
+ # Start conversation
421
+ user_proxy.initiate_chat(
422
+ manager,
423
+ message=f"""
424
+ User profile:
425
+ - Name: {name}
426
+ - Location: {location}
427
+ - Age: {age}
428
+ - Marital Status: {marital_status}
429
+ - Assets: {asset_values}
430
+ - Debts: {debt_values}
431
+ - Monthly Savings: {currency_symbol}{monthly_savings}
432
+ - Target Amount: {currency_symbol}{target_amount}
433
+ - Target Time: {target_years} years
434
+
435
+ Task:
436
+ 1. Analyze feasibility of achieving the target amount of {currency_symbol}{target_amount} in {target_years} years.
437
+ 2. Provide investment recommendations specific to {location} market.
438
+ 3. Suggest tax-saving strategies available in {location}.
439
+ """
440
+ )
441
+
442
+ # Modified message filtering logic
443
+ if len(group_chat.messages) > 0:
444
+ # Create a placeholder for each agent
445
+ output = {}
446
+ for agent in ["Financial_Planner", "Market_Analyst", "Tax_Advisor"]:
447
+ output[agent] = []
448
+
449
+ # Collect messages by agent
450
+ for msg in group_chat.messages:
451
+ if 'name' in msg and msg['name'] in output:
452
+ content = msg['content'].strip()
453
+ if content and not content.startswith("Next speaker:"):
454
+ output[msg['name']].append(content)
455
+
456
+ # Display messages from each agent
457
+ for agent, messages in output.items():
458
+ if messages:
459
+ st.subheader(f"{agent.replace('_', ' ')} Analysis")
460
+ for msg in messages:
461
+ st.markdown(msg)
462
+ st.markdown("---")
463
+
464
+ # Investment Growth Projection Chart
465
+ st.subheader("Investment Growth Projection")
466
+
467
+ # Simplified projection calculation
468
+ years = list(range(1, target_years + 1))
469
+
470
+ # Conservative scenario (lower return rate)
471
+ conservative_rate = country_data[location]['base_interest_rate'] - 1.0
472
+ conservative_values = [
473
+ monthly_savings * 12 * (((1 + conservative_rate/100) ** y) - 1) / (conservative_rate/100)
474
+ for y in years
475
+ ]
476
+
477
+ # Moderate scenario
478
+ moderate_rate = country_data[location]['base_interest_rate'] + 1.0
479
+ moderate_values = [
480
+ monthly_savings * 12 * (((1 + moderate_rate/100) ** y) - 1) / (moderate_rate/100)
481
+ for y in years
482
+ ]
483
+
484
+ # Aggressive scenario
485
+ aggressive_rate = country_data[location]['base_interest_rate'] + 3.0
486
+ aggressive_values = [
487
+ monthly_savings * 12 * (((1 + aggressive_rate/100) ** y) - 1) / (aggressive_rate/100)
488
+ for y in years
489
+ ]
490
+
491
+ # Target line
492
+ target_line = [target_amount] * len(years)
493
+
494
+ # Create figure
495
+ fig = go.Figure()
496
+
497
+ # Add traces
498
+ fig.add_trace(go.Scatter(
499
+ x=years, y=conservative_values,
500
+ mode='lines',
501
+ name=f'Conservative ({conservative_rate:.1f}%)',
502
+ line=dict(color='blue', dash='dash')
503
+ ))
504
+
505
+ fig.add_trace(go.Scatter(
506
+ x=years, y=moderate_values,
507
+ mode='lines',
508
+ name=f'Moderate ({moderate_rate:.1f}%)',
509
+ line=dict(color='green')
510
+ ))
511
+
512
+ fig.add_trace(go.Scatter(
513
+ x=years, y=aggressive_values,
514
+ mode='lines',
515
+ name=f'Aggressive ({aggressive_rate:.1f}%)',
516
+ line=dict(color='red', dash='dot')
517
+ ))
518
+
519
+ fig.add_trace(go.Scatter(
520
+ x=years, y=target_line,
521
+ mode='lines',
522
+ name='Target Amount',
523
+ line=dict(color='black', dash='dash')
524
+ ))
525
+
526
+ # Update layout
527
+ fig.update_layout(
528
+ title=f'Projected Growth of Monthly Investment ({currency_symbol}{monthly_savings}/month)',
529
+ xaxis_title='Years',
530
+ yaxis_title=f'Value ({currency_symbol})',
531
+ legend=dict(y=0.5, traceorder='reversed'),
532
+ hovermode='x unified'
533
+ )
534
+
535
+ # Format y-axis with appropriate currency
536
+ fig.update_layout(yaxis=dict(
537
+ tickprefix=currency_symbol,
538
+ tickformat=",."
539
+ ))
540
+
541
+ st.plotly_chart(fig, use_container_width=True)
542
+
543
+ # If no valid messages were found, show a more user-friendly message
544
+ if all(len(msgs) == 0 for msgs in output.values()):
545
+ st.info("""
546
+ Our advisors are still analyzing your financial situation.
547
+ Please ensure you've entered all required information and try again.
548
+ """)
549
+
550
+ else:
551
+ st.info("Our advisors are preparing your personalized financial analysis. Please try again in a moment.")
552
+
553
+ st.markdown('</div>', unsafe_allow_html=True)