Sujatha commited on
Commit
7ac1427
·
verified ·
1 Parent(s): fabd229

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +176 -192
app.py CHANGED
@@ -57,19 +57,9 @@ class FinancialSpacesAgent:
57
  device_map="auto" if torch.cuda.is_available() else "cpu"
58
  )
59
 
60
- # 2. Mini summarizer
61
- try:
62
- self.summarizer = pipeline(
63
- "summarization",
64
- model="sshleifer/distilbart-cnn-12-6",
65
- device_map="auto" if torch.cuda.is_available() else "cpu",
66
- max_length=100,
67
- min_length=30
68
- )
69
- print("✅ Summarization model loaded")
70
- except:
71
- self.summarizer = None
72
- print("⚠️ Summarization model skipped")
73
 
74
  # 3. Lightweight embeddings
75
  try:
@@ -78,8 +68,8 @@ class FinancialSpacesAgent:
78
  except:
79
  self.embedder = None
80
 
81
- # 4. Text generation (optional - memory intensive)
82
- self.text_generator = None # Skip to save memory
83
 
84
  self.models_loaded = True
85
  print("🎉 All models loaded successfully!")
@@ -113,7 +103,7 @@ class FinancialSpacesAgent:
113
  'history_1y': stock.history(period="1y"),
114
  'history_5y': stock.history(period="5y"),
115
  'dividends': stock.dividends,
116
- 'news': getattr(stock, 'news', [])[:10] # Limit news
117
  }
118
 
119
  # Calculate key metrics
@@ -184,24 +174,21 @@ class FinancialSpacesAgent:
184
 
185
  # Create subplots
186
  from plotly.subplots import make_subplots
187
- import plotly.graph_objects as go
188
 
189
  fig = make_subplots(
190
- rows=2, cols=3,
191
  subplot_titles=(
192
  '📈 Price Trend',
193
  '💰 Key Metrics',
194
  '📊 Financial Health',
195
- '📰 News Sentiment',
196
- '📅 Historical Performance',
197
  '🎯 Recommendation'
198
  ),
199
  specs=[
200
- [{"type": "scatter"}, {"type": "bar"}, {"type": "indicator"}],
201
- [{"type": "bar"}, {"type": "scatter"}, {"type": "indicator"}]
202
  ],
203
- vertical_spacing=0.15,
204
- horizontal_spacing=0.1
205
  )
206
 
207
  # 1. Price Trend
@@ -232,6 +219,9 @@ class FinancialSpacesAgent:
232
  ),
233
  row=1, col=1
234
  )
 
 
 
235
 
236
  # 2. Key Metrics Bar Chart
237
  if metrics:
@@ -242,29 +232,36 @@ class FinancialSpacesAgent:
242
 
243
  for key in metric_keys:
244
  val = metrics.get(key, 0)
245
- metric_values.append(val if isinstance(val, (int, float)) else 0)
246
-
247
- # Color coding
248
- if key == 'roe':
249
- metric_colors.append('#2E86AB' if val > 15 else '#A23B72')
250
- elif key == 'net_margin':
251
- metric_colors.append('#2E86AB' if val > 10 else '#A23B72')
252
- elif key == 'current_ratio':
253
- metric_colors.append('#2E86AB' if val > 1.5 else '#A23B72')
254
- elif key == 'debt_to_equity':
255
- metric_colors.append('#2E86AB' if val < 1 else '#A23B72')
 
 
 
 
256
 
257
  fig.add_trace(
258
  go.Bar(
259
  x=metric_labels,
260
  y=metric_values,
261
  marker_color=metric_colors,
262
- text=[f'{v:.1f}' for v in metric_values],
263
  textposition='auto',
264
  name='Metrics'
265
  ),
266
  row=1, col=2
267
  )
 
 
 
268
 
269
  # 3. Financial Health Gauge
270
  health_score = self.calculate_health_score(metrics)
@@ -288,50 +285,10 @@ class FinancialSpacesAgent:
288
  }
289
  }
290
  ),
291
- row=1, col=3
292
  )
293
 
294
- # 4. News Sentiment
295
- news = data.get('news', [])
296
- if news and self.models_loaded:
297
- sentiments = []
298
- for item in news[:5]:
299
- title = item.get('title', '')
300
- if title:
301
- try:
302
- sentiment = self.sentiment_model(title[:100])[0]
303
- sentiments.append(1 if sentiment['label'] == 'positive' else -1 if sentiment['label'] == 'negative' else 0)
304
- except:
305
- sentiments.append(0)
306
-
307
- if sentiments:
308
- fig.add_trace(
309
- go.Bar(
310
- x=['News 1', 'News 2', 'News 3', 'News 4', 'News 5'][:len(sentiments)],
311
- y=sentiments,
312
- marker_color=['green' if s > 0 else 'red' if s < 0 else 'gray' for s in sentiments],
313
- name='Sentiment'
314
- ),
315
- row=2, col=1
316
- )
317
-
318
- # 5. Historical Returns
319
- if not history.empty and len(history) > 20:
320
- returns = history['Close'].pct_change().dropna()
321
- fig.add_trace(
322
- go.Scatter(
323
- x=returns.index,
324
- y=returns * 100,
325
- mode='lines',
326
- name='Daily Returns %',
327
- line=dict(color='#6BAA75', width=1),
328
- fill='tozeroy',
329
- fillcolor='rgba(107, 170, 117, 0.2)'
330
- ),
331
- row=2, col=2
332
- )
333
-
334
- # 6. Recommendation Indicator
335
  recommendation = self.generate_recommendation(metrics)
336
  color_map = {
337
  'Strong Buy': 'green',
@@ -343,18 +300,18 @@ class FinancialSpacesAgent:
343
 
344
  fig.add_trace(
345
  go.Indicator(
346
- mode="delta",
347
  value=health_score,
348
  title={'text': f"Recommendation: {recommendation}"},
349
- delta={'reference': 5, 'position': "bottom"},
350
- domain={'row': 1, 'column': 3}
351
  ),
352
- row=2, col=3
353
  )
354
 
355
  # Update layout
356
  fig.update_layout(
357
- height=800,
358
  showlegend=True,
359
  title_text=f"📊 Financial Dashboard - {ticker}",
360
  title_font_size=20,
@@ -368,11 +325,16 @@ class FinancialSpacesAgent:
368
  # Return simple figure
369
  fig = go.Figure()
370
  fig.add_annotation(
371
- text="Dashboard generation failed",
372
  xref="paper", yref="paper",
373
  x=0.5, y=0.5,
374
  showarrow=False,
375
- font_size=20
 
 
 
 
 
376
  )
377
  return fig
378
 
@@ -443,90 +405,59 @@ class FinancialSpacesAgent:
443
  def generate_ai_analysis(self, ticker, data):
444
  """Generate AI analysis of company"""
445
  try:
446
- if not self.models_loaded:
447
- return self.generate_basic_analysis(ticker, data)
448
-
449
  metrics = data.get('metrics', {})
450
 
451
- # Create analysis prompt
452
- prompt = f"""
453
- Company: {ticker}
454
 
455
- Key Financial Metrics:
456
  """
457
 
458
- for key, value in metrics.items():
459
- if isinstance(value, (int, float)):
460
- prompt += f"{key.replace('_', ' ').title()}: {value:.2f}\n"
 
 
 
 
461
 
462
- prompt += "\nProvide a brief financial analysis focusing on strengths and weaknesses."
 
 
 
463
 
464
- # Use sentiment model to generate analysis
465
- try:
466
- analysis = self.sentiment_model(prompt[:200])[0]
467
- sentiment = analysis['label']
468
- confidence = analysis['score']
469
-
470
- if sentiment == 'positive':
471
- conclusion = f"Overall positive outlook with {confidence:.1%} confidence."
472
- elif sentiment == 'negative':
473
- conclusion = f"Concerns identified with {confidence:.1%} confidence."
474
- else:
475
- conclusion = f"Neutral assessment with {confidence:.1%} confidence."
476
-
477
- return f"""
478
- ## 🤖 AI Analysis for {ticker}
479
-
480
- **Sentiment:** {sentiment.title()}
481
- **Confidence:** {confidence:.1%}
482
-
483
- **Key Observations:**
484
- {conclusion}
485
-
486
- **Financial Health Score:** {self.calculate_health_score(metrics)}/10
487
- **Recommendation:** {self.generate_recommendation(metrics)}
488
-
489
- *Note: AI analysis is for educational purposes only.*
490
- """
491
-
492
- except:
493
- return self.generate_basic_analysis(ticker, data)
494
 
495
  except Exception as e:
496
  return f"Error in AI analysis: {str(e)}"
497
 
498
- def generate_basic_analysis(self, ticker, data):
499
- """Generate basic analysis when AI models aren't available"""
500
- metrics = data.get('metrics', {})
501
-
502
- analysis = f"""
503
- ## 📊 Basic Analysis for {ticker}
504
-
505
- ### Key Metrics:
506
- """
507
-
508
- for key, value in metrics.items():
509
- if isinstance(value, (int, float)):
510
- if 'margin' in key or 'roe' in key:
511
- analysis += f"• {key.replace('_', ' ').title()}: **{value:.1f}%**\n"
512
- else:
513
- analysis += f"• {key.replace('_', ' ').title()}: **{value:.2f}**\n"
514
-
515
- analysis += f"""
516
-
517
- ### Financial Health Score: {self.calculate_health_score(metrics)}/10
518
- ### Recommendation: {self.generate_recommendation(metrics)}
519
-
520
- ---
521
- *Data Source: Yahoo Finance*
522
- """
523
-
524
- return analysis
525
-
526
  def create_metrics_table(self, metrics):
527
  """Create a nice HTML table for metrics"""
528
  if not metrics:
529
- return "No metrics available"
530
 
531
  table_html = """
532
  <style>
@@ -535,12 +466,14 @@ class FinancialSpacesAgent:
535
  border-collapse: collapse;
536
  margin: 10px 0;
537
  font-family: Arial, sans-serif;
 
538
  }
539
  .metrics-table th {
540
  background-color: #2E86AB;
541
  color: white;
542
  padding: 10px;
543
  text-align: left;
 
544
  }
545
  .metrics-table td {
546
  padding: 8px 10px;
@@ -549,9 +482,9 @@ class FinancialSpacesAgent:
549
  .metrics-table tr:hover {
550
  background-color: #f5f5f5;
551
  }
552
- .good { color: green; font-weight: bold; }
553
- .warning { color: orange; font-weight: bold; }
554
- .poor { color: red; font-weight: bold; }
555
  </style>
556
 
557
  <table class="metrics-table">
@@ -565,10 +498,12 @@ class FinancialSpacesAgent:
565
  for key, value in metrics.items():
566
  if isinstance(value, (int, float)):
567
  # Format value
568
- if 'margin' in key or 'roe' in key:
569
  display_value = f"{value:.1f}%"
570
- else:
571
  display_value = f"{value:.2f}"
 
 
572
 
573
  # Determine assessment
574
  assessment = ""
@@ -581,9 +516,12 @@ class FinancialSpacesAgent:
581
  elif value > 8:
582
  assessment = "Good"
583
  css_class = "good"
584
- else:
585
- assessment = "Needs Improvement"
586
  css_class = "warning"
 
 
 
587
 
588
  elif key == 'net_margin':
589
  if value > 15:
@@ -591,9 +529,13 @@ class FinancialSpacesAgent:
591
  css_class = "good"
592
  elif value > 5:
593
  assessment = "Good"
594
- else:
 
595
  assessment = "Low"
596
  css_class = "warning"
 
 
 
597
 
598
  elif key == 'current_ratio':
599
  if value > 2:
@@ -601,6 +543,7 @@ class FinancialSpacesAgent:
601
  css_class = "good"
602
  elif value > 1:
603
  assessment = "Adequate"
 
604
  else:
605
  assessment = "Risk"
606
  css_class = "warning"
@@ -611,10 +554,32 @@ class FinancialSpacesAgent:
611
  css_class = "good"
612
  elif value < 1:
613
  assessment = "Moderate"
 
 
 
614
  else:
615
- assessment = "High Leverage"
 
 
 
 
 
 
 
 
 
 
616
  css_class = "warning"
617
 
 
 
 
 
 
 
 
 
 
618
  table_html += f"""
619
  <tr>
620
  <td>{key.replace('_', ' ').title()}</td>
@@ -629,7 +594,7 @@ class FinancialSpacesAgent:
629
  # Initialize agent
630
  agent = FinancialSpacesAgent()
631
 
632
- # Create Gradio interface
633
  def analyze_company_gradio(ticker):
634
  """Main Gradio analysis function"""
635
  if not ticker:
@@ -663,6 +628,7 @@ def analyze_company_gradio(ticker):
663
  **Current Price:** ${info.get('currentPrice', 'N/A')}
664
  **52W High:** ${info.get('fiftyTwoWeekHigh', 'N/A')}
665
  **52W Low:** ${info.get('fiftyTwoWeekLow', 'N/A')}
 
666
  """
667
 
668
  return analysis, dashboard, metrics_table, basic_info
@@ -682,7 +648,7 @@ def compare_companies_gradio(ticker1, ticker2):
682
  metrics2 = data2.get('metrics', {})
683
 
684
  # Create comparison table
685
- comparison_metrics = ['roe', 'net_margin', 'current_ratio', 'debt_to_equity', 'pe_ratio']
686
 
687
  comparison_data = []
688
  for metric in comparison_metrics:
@@ -696,36 +662,52 @@ def compare_companies_gradio(ticker1, ticker2):
696
  })
697
 
698
  # Create comparison chart
699
- import plotly.graph_objects as go
700
-
701
  fig = go.Figure()
702
 
703
- for i, metric in enumerate(comparison_metrics[:4]):
 
 
 
 
 
704
  val1 = metrics1.get(metric, 0)
705
  val2 = metrics2.get(metric, 0)
706
 
707
  if isinstance(val1, (int, float)) and isinstance(val2, (int, float)):
708
- fig.add_trace(go.Bar(
709
- name=metric.replace('_', ' ').title(),
710
- x=[ticker1, ticker2],
711
- y=[val1, val2],
712
- text=[f'{val1:.1f}', f'{val2:.1f}'],
713
- textposition='auto',
714
- ))
715
-
716
- fig.update_layout(
717
- title=f"{ticker1} vs {ticker2} Comparison",
718
- barmode='group',
719
- template="plotly_white"
720
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
721
 
722
  # Create comparison text
723
  comparison_text = f"## ⚖️ {ticker1} vs {ticker2}\n\n"
724
  comparison_text += "| Metric | " + ticker1 + " | " + ticker2 + " |\n"
725
  comparison_text += "|--------|" + "-" * (len(ticker1) + 2) + "|" + "-" * (len(ticker2) + 2) + "|\n"
726
 
727
- for row in comparison_data:
728
- comparison_text += f"| {row['Metric']} | {row[ticker1]} | {row[ticker2]} |\n"
729
 
730
  return comparison_text, fig
731
 
@@ -763,12 +745,14 @@ with gr.Blocks(
763
 
764
  gr.Markdown("### 📊 Popular Companies")
765
  with gr.Row():
766
- popular_tickers = ["AAPL", "MSFT", "GOOGL", "TSLA", "AMZN", "META"]
767
  for t in popular_tickers:
768
- gr.Button(t, size="sm").click(
769
- lambda t=t: (t, None, None, None),
 
 
770
  inputs=None,
771
- outputs=[ticker_input, None, None, None]
772
  )
773
 
774
  with gr.Column(scale=2):
@@ -782,7 +766,7 @@ with gr.Blocks(
782
  metrics_output = gr.HTML(label="Key Metrics")
783
 
784
  with gr.Row():
785
- analysis_output = gr.Markdown(label="AI Analysis Report", elem_classes=["analysis-box"])
786
 
787
  with gr.TabItem("⚖️ Compare Companies"):
788
  with gr.Row():
@@ -899,7 +883,7 @@ with gr.Blocks(
899
  outputs=[comparison_output, comparison_plot]
900
  )
901
 
902
- # Auto-load example
903
  demo.load(
904
  lambda: analyze_company_gradio("AAPL"),
905
  inputs=None,
@@ -912,6 +896,6 @@ if __name__ == "__main__":
912
  server_name="0.0.0.0",
913
  server_port=7860,
914
  share=False,
915
- favicon_path=None,
916
- show_error=True
917
  )
 
57
  device_map="auto" if torch.cuda.is_available() else "cpu"
58
  )
59
 
60
+ # 2. Mini summarizer (skip to save memory)
61
+ self.summarizer = None
62
+ print("⚠️ Summarization model skipped to save memory")
 
 
 
 
 
 
 
 
 
 
63
 
64
  # 3. Lightweight embeddings
65
  try:
 
68
  except:
69
  self.embedder = None
70
 
71
+ # 4. Text generation (skip to save memory)
72
+ self.text_generator = None
73
 
74
  self.models_loaded = True
75
  print("🎉 All models loaded successfully!")
 
103
  'history_1y': stock.history(period="1y"),
104
  'history_5y': stock.history(period="5y"),
105
  'dividends': stock.dividends,
106
+ 'news': getattr(stock, 'news', [])[:5] # Limit news to save memory
107
  }
108
 
109
  # Calculate key metrics
 
174
 
175
  # Create subplots
176
  from plotly.subplots import make_subplots
 
177
 
178
  fig = make_subplots(
179
+ rows=2, cols=2,
180
  subplot_titles=(
181
  '📈 Price Trend',
182
  '💰 Key Metrics',
183
  '📊 Financial Health',
 
 
184
  '🎯 Recommendation'
185
  ),
186
  specs=[
187
+ [{"type": "scatter"}, {"type": "bar"}],
188
+ [{"type": "indicator"}, {"type": "indicator"}]
189
  ],
190
+ vertical_spacing=0.2,
191
+ horizontal_spacing=0.15
192
  )
193
 
194
  # 1. Price Trend
 
219
  ),
220
  row=1, col=1
221
  )
222
+
223
+ fig.update_xaxes(title_text="Date", row=1, col=1)
224
+ fig.update_yaxes(title_text="Price ($)", row=1, col=1)
225
 
226
  # 2. Key Metrics Bar Chart
227
  if metrics:
 
232
 
233
  for key in metric_keys:
234
  val = metrics.get(key, 0)
235
+ if isinstance(val, (int, float)):
236
+ metric_values.append(val)
237
+
238
+ # Color coding
239
+ if key == 'roe':
240
+ metric_colors.append('#2E86AB' if val > 15 else '#A23B72' if val > 8 else '#C73E1D')
241
+ elif key == 'net_margin':
242
+ metric_colors.append('#2E86AB' if val > 10 else '#A23B72' if val > 5 else '#C73E1D')
243
+ elif key == 'current_ratio':
244
+ metric_colors.append('#2E86AB' if val > 1.5 else '#A23B72' if val > 1 else '#C73E1D')
245
+ elif key == 'debt_to_equity':
246
+ metric_colors.append('#2E86AB' if val < 1 else '#A23B72' if val < 2 else '#C73E1D')
247
+ else:
248
+ metric_values.append(0)
249
+ metric_colors.append('#CCCCCC')
250
 
251
  fig.add_trace(
252
  go.Bar(
253
  x=metric_labels,
254
  y=metric_values,
255
  marker_color=metric_colors,
256
+ text=[f'{v:.1f}' if isinstance(v, (int, float)) else 'N/A' for v in metric_values],
257
  textposition='auto',
258
  name='Metrics'
259
  ),
260
  row=1, col=2
261
  )
262
+
263
+ fig.update_xaxes(title_text="Metrics", row=1, col=2, tickangle=45)
264
+ fig.update_yaxes(title_text="Value", row=1, col=2)
265
 
266
  # 3. Financial Health Gauge
267
  health_score = self.calculate_health_score(metrics)
 
285
  }
286
  }
287
  ),
288
+ row=2, col=1
289
  )
290
 
291
+ # 4. Recommendation Indicator
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
  recommendation = self.generate_recommendation(metrics)
293
  color_map = {
294
  'Strong Buy': 'green',
 
300
 
301
  fig.add_trace(
302
  go.Indicator(
303
+ mode="number",
304
  value=health_score,
305
  title={'text': f"Recommendation: {recommendation}"},
306
+ number={'font': {'color': color_map.get(recommendation, 'black'), 'size': 24}},
307
+ domain={'row': 2, 'column': 2}
308
  ),
309
+ row=2, col=2
310
  )
311
 
312
  # Update layout
313
  fig.update_layout(
314
+ height=700,
315
  showlegend=True,
316
  title_text=f"📊 Financial Dashboard - {ticker}",
317
  title_font_size=20,
 
325
  # Return simple figure
326
  fig = go.Figure()
327
  fig.add_annotation(
328
+ text="Dashboard generation failed<br>Try a different ticker",
329
  xref="paper", yref="paper",
330
  x=0.5, y=0.5,
331
  showarrow=False,
332
+ font_size=16,
333
+ align="center"
334
+ )
335
+ fig.update_layout(
336
+ title=f"Error for {ticker}",
337
+ height=400
338
  )
339
  return fig
340
 
 
405
  def generate_ai_analysis(self, ticker, data):
406
  """Generate AI analysis of company"""
407
  try:
 
 
 
408
  metrics = data.get('metrics', {})
409
 
410
+ # Create analysis
411
+ analysis = f"""
412
+ ## 🤖 AI Analysis for {ticker}
413
 
414
+ ### 📊 Key Metrics Analysis:
415
  """
416
 
417
+ # Add metric analysis
418
+ metric_analysis = {
419
+ 'roe': "Return on Equity measures how effectively management is using shareholders' funds.",
420
+ 'net_margin': "Net Profit Margin shows what percentage of revenue is actual profit.",
421
+ 'current_ratio': "Current Ratio indicates short-term liquidity and ability to pay debts.",
422
+ 'debt_to_equity': "Debt-to-Equity ratio shows the company's financial leverage."
423
+ }
424
 
425
+ for key, desc in metric_analysis.items():
426
+ val = metrics.get(key, 'N/A')
427
+ if isinstance(val, (int, float)):
428
+ analysis += f"**{key.replace('_', ' ').title()}**: {val:.1f} - {desc}\n\n"
429
 
430
+ # Add overall assessment
431
+ health_score = self.calculate_health_score(metrics)
432
+ recommendation = self.generate_recommendation(metrics)
433
+
434
+ analysis += f"""
435
+ ### 🏥 Financial Health Score: **{health_score}/10**
436
+
437
+ ### 🎯 Recommendation: **{recommendation}**
438
+
439
+ ### 📈 Market Outlook:
440
+ """
441
+
442
+ # Add simple outlook based on metrics
443
+ if health_score >= 7:
444
+ analysis += "The company shows strong financial fundamentals with good profitability and manageable leverage."
445
+ elif health_score >= 5:
446
+ analysis += "The company has average financial health with room for improvement in some areas."
447
+ else:
448
+ analysis += "The company shows concerning financial metrics that warrant caution."
449
+
450
+ analysis += "\n\n*Note: This analysis is AI-generated for educational purposes only.*"
451
+
452
+ return analysis
 
 
 
 
 
 
 
453
 
454
  except Exception as e:
455
  return f"Error in AI analysis: {str(e)}"
456
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
457
  def create_metrics_table(self, metrics):
458
  """Create a nice HTML table for metrics"""
459
  if not metrics:
460
+ return "<p>No metrics available</p>"
461
 
462
  table_html = """
463
  <style>
 
466
  border-collapse: collapse;
467
  margin: 10px 0;
468
  font-family: Arial, sans-serif;
469
+ font-size: 14px;
470
  }
471
  .metrics-table th {
472
  background-color: #2E86AB;
473
  color: white;
474
  padding: 10px;
475
  text-align: left;
476
+ font-weight: bold;
477
  }
478
  .metrics-table td {
479
  padding: 8px 10px;
 
482
  .metrics-table tr:hover {
483
  background-color: #f5f5f5;
484
  }
485
+ .good { color: #28a745; font-weight: bold; }
486
+ .warning { color: #ffc107; font-weight: bold; }
487
+ .poor { color: #dc3545; font-weight: bold; }
488
  </style>
489
 
490
  <table class="metrics-table">
 
498
  for key, value in metrics.items():
499
  if isinstance(value, (int, float)):
500
  # Format value
501
+ if 'margin' in key or 'roe' in key or 'yield' in key:
502
  display_value = f"{value:.1f}%"
503
+ elif 'ratio' in key or 'beta' in key:
504
  display_value = f"{value:.2f}"
505
+ else:
506
+ display_value = f"{value:,.0f}" if value > 1000 else f"{value:.1f}"
507
 
508
  # Determine assessment
509
  assessment = ""
 
516
  elif value > 8:
517
  assessment = "Good"
518
  css_class = "good"
519
+ elif value > 0:
520
+ assessment = "Poor"
521
  css_class = "warning"
522
+ else:
523
+ assessment = "Negative"
524
+ css_class = "poor"
525
 
526
  elif key == 'net_margin':
527
  if value > 15:
 
529
  css_class = "good"
530
  elif value > 5:
531
  assessment = "Good"
532
+ css_class = "good"
533
+ elif value > 0:
534
  assessment = "Low"
535
  css_class = "warning"
536
+ else:
537
+ assessment = "Negative"
538
+ css_class = "poor"
539
 
540
  elif key == 'current_ratio':
541
  if value > 2:
 
543
  css_class = "good"
544
  elif value > 1:
545
  assessment = "Adequate"
546
+ css_class = "good"
547
  else:
548
  assessment = "Risk"
549
  css_class = "warning"
 
554
  css_class = "good"
555
  elif value < 1:
556
  assessment = "Moderate"
557
+ elif value < 2:
558
+ assessment = "High"
559
+ css_class = "warning"
560
  else:
561
+ assessment = "Very High"
562
+ css_class = "poor"
563
+
564
+ elif key == 'pe_ratio' and isinstance(value, (int, float)):
565
+ if value < 15:
566
+ assessment = "Undervalued"
567
+ css_class = "good"
568
+ elif value < 25:
569
+ assessment = "Fair"
570
+ else:
571
+ assessment = "Overvalued"
572
  css_class = "warning"
573
 
574
+ elif key == 'dividend_yield' and isinstance(value, (int, float)):
575
+ if value > 4:
576
+ assessment = "High Yield"
577
+ css_class = "good"
578
+ elif value > 2:
579
+ assessment = "Moderate"
580
+ else:
581
+ assessment = "Low"
582
+
583
  table_html += f"""
584
  <tr>
585
  <td>{key.replace('_', ' ').title()}</td>
 
594
  # Initialize agent
595
  agent = FinancialSpacesAgent()
596
 
597
+ # Create Gradio interface functions
598
  def analyze_company_gradio(ticker):
599
  """Main Gradio analysis function"""
600
  if not ticker:
 
628
  **Current Price:** ${info.get('currentPrice', 'N/A')}
629
  **52W High:** ${info.get('fiftyTwoWeekHigh', 'N/A')}
630
  **52W Low:** ${info.get('fiftyTwoWeekLow', 'N/A')}
631
+ **Beta:** {info.get('beta', 'N/A')}
632
  """
633
 
634
  return analysis, dashboard, metrics_table, basic_info
 
648
  metrics2 = data2.get('metrics', {})
649
 
650
  # Create comparison table
651
+ comparison_metrics = ['roe', 'net_margin', 'current_ratio', 'debt_to_equity', 'pe_ratio', 'dividend_yield']
652
 
653
  comparison_data = []
654
  for metric in comparison_metrics:
 
662
  })
663
 
664
  # Create comparison chart
 
 
665
  fig = go.Figure()
666
 
667
+ # Get values for first 4 metrics
668
+ metric_keys = comparison_metrics[:4]
669
+ ticker1_vals = []
670
+ ticker2_vals = []
671
+
672
+ for metric in metric_keys:
673
  val1 = metrics1.get(metric, 0)
674
  val2 = metrics2.get(metric, 0)
675
 
676
  if isinstance(val1, (int, float)) and isinstance(val2, (int, float)):
677
+ ticker1_vals.append(val1)
678
+ ticker2_vals.append(val2)
679
+
680
+ if ticker1_vals and ticker2_vals:
681
+ x_labels = [m.replace('_', ' ').title() for m in metric_keys[:len(ticker1_vals)]]
682
+
683
+ fig.add_trace(go.Bar(
684
+ name=ticker1,
685
+ x=x_labels,
686
+ y=ticker1_vals,
687
+ marker_color='#2E86AB'
688
+ ))
689
+
690
+ fig.add_trace(go.Bar(
691
+ name=ticker2,
692
+ x=x_labels,
693
+ y=ticker2_vals,
694
+ marker_color='#F18F01'
695
+ ))
696
+
697
+ fig.update_layout(
698
+ title=f"{ticker1} vs {ticker2} - Key Metrics Comparison",
699
+ barmode='group',
700
+ template="plotly_white",
701
+ height=400
702
+ )
703
 
704
  # Create comparison text
705
  comparison_text = f"## ⚖️ {ticker1} vs {ticker2}\n\n"
706
  comparison_text += "| Metric | " + ticker1 + " | " + ticker2 + " |\n"
707
  comparison_text += "|--------|" + "-" * (len(ticker1) + 2) + "|" + "-" * (len(ticker2) + 2) + "|\n"
708
 
709
+ for comp in comparison_data:
710
+ comparison_text += f"| {comp['Metric']} | {comp[ticker1]} | {comp[ticker2]} |\n"
711
 
712
  return comparison_text, fig
713
 
 
745
 
746
  gr.Markdown("### 📊 Popular Companies")
747
  with gr.Row():
748
+ popular_tickers = ["AAPL", "MSFT", "GOOGL", "TSLA"]
749
  for t in popular_tickers:
750
+ btn = gr.Button(t, size="sm")
751
+ # FIXED: Only update the ticker input, not other outputs
752
+ btn.click(
753
+ lambda t=t: t,
754
  inputs=None,
755
+ outputs=ticker_input
756
  )
757
 
758
  with gr.Column(scale=2):
 
766
  metrics_output = gr.HTML(label="Key Metrics")
767
 
768
  with gr.Row():
769
+ analysis_output = gr.Markdown(label="AI Analysis Report")
770
 
771
  with gr.TabItem("⚖️ Compare Companies"):
772
  with gr.Row():
 
883
  outputs=[comparison_output, comparison_plot]
884
  )
885
 
886
+ # Auto-load example on startup
887
  demo.load(
888
  lambda: analyze_company_gradio("AAPL"),
889
  inputs=None,
 
896
  server_name="0.0.0.0",
897
  server_port=7860,
898
  share=False,
899
+ show_error=True,
900
+ debug=False # Disable debug mode for production
901
  )