vn6295337 Claude Opus 4.5 commited on
Commit
a5c7991
·
1 Parent(s): de4ad41

Frontend: Convert metric names to human-readable labels

Browse files

Add METRIC_LABELS mapping and formatMetricName() function to convert
snake_case metric names (e.g., net_income, trailing_pe) to readable
labels (e.g., "Net Income", "Trailing P/E") in the Quantitative Data table.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

frontend/src/components/MCPDataPanel.tsx CHANGED
@@ -17,6 +17,70 @@ interface MCPDataPanelProps {
17
  cik?: string
18
  }
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  // Format numbers for display
21
  function formatValue(value: string | number): string {
22
  if (value === null || value === undefined) return '—'
@@ -361,7 +425,7 @@ export function MCPDataPanel({ metrics, rawData, companyName, ticker, exchange,
361
  {quantitativeRows.map((row, idx) => (
362
  <tr key={idx} className="hover:bg-muted/20">
363
  <td className="px-3 py-1.5 text-muted-foreground">{idx + 1}</td>
364
- <td className="px-3 py-1.5">{row.metric}</td>
365
  <td className="px-3 py-1.5 text-right font-medium">{row.value}</td>
366
  <td className="px-3 py-1.5 text-muted-foreground">{row.dataType}</td>
367
  <td className="px-3 py-1.5 text-muted-foreground">{row.asOf}</td>
 
17
  cik?: string
18
  }
19
 
20
+ // Metric name mapping: snake_case → Human Readable
21
+ const METRIC_LABELS: Record<string, string> = {
22
+ // Fundamentals
23
+ revenue: 'Revenue',
24
+ net_income: 'Net Income',
25
+ gross_profit: 'Gross Profit',
26
+ operating_income: 'Operating Income',
27
+ gross_margin_pct: 'Gross Margin %',
28
+ operating_margin_pct: 'Operating Margin %',
29
+ net_margin_pct: 'Net Margin %',
30
+ free_cash_flow: 'Free Cash Flow',
31
+ operating_cash_flow: 'Operating Cash Flow',
32
+ total_assets: 'Total Assets',
33
+ total_liabilities: 'Total Liabilities',
34
+ stockholders_equity: "Stockholders' Equity",
35
+ cash: 'Cash',
36
+ long_term_debt: 'Long-term Debt',
37
+ net_debt: 'Net Debt',
38
+ debt_to_equity: 'Debt to Equity',
39
+ rd_expense: 'R&D Expense',
40
+ eps: 'EPS',
41
+
42
+ // Valuation
43
+ market_cap: 'Market Cap',
44
+ enterprise_value: 'Enterprise Value',
45
+ trailing_pe: 'Trailing P/E',
46
+ forward_pe: 'Forward P/E',
47
+ pb_ratio: 'P/B Ratio',
48
+ ps_ratio: 'P/S Ratio',
49
+ trailing_peg: 'PEG Ratio',
50
+ price_to_fcf: 'Price/FCF',
51
+ ev_ebitda: 'EV/EBITDA',
52
+ ev_revenue: 'EV/Revenue',
53
+ revenue_growth: 'Revenue Growth',
54
+ earnings_growth: 'Earnings Growth',
55
+
56
+ // Volatility
57
+ vix: 'VIX',
58
+ vxn: 'VXN',
59
+ beta: 'Beta',
60
+ historical_volatility: 'Historical Volatility',
61
+ implied_volatility: 'Implied Volatility',
62
+
63
+ // Macro
64
+ gdp_growth: 'GDP Growth',
65
+ interest_rate: 'Interest Rate',
66
+ cpi_inflation: 'CPI Inflation',
67
+ unemployment: 'Unemployment',
68
+ }
69
+
70
+ // Convert snake_case metric name to human-readable label
71
+ function formatMetricName(metric: string): string {
72
+ // Check if we have a predefined label
73
+ if (METRIC_LABELS[metric]) {
74
+ return METRIC_LABELS[metric]
75
+ }
76
+
77
+ // Fallback: convert snake_case to Title Case
78
+ return metric
79
+ .split('_')
80
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
81
+ .join(' ')
82
+ }
83
+
84
  // Format numbers for display
85
  function formatValue(value: string | number): string {
86
  if (value === null || value === undefined) return '—'
 
425
  {quantitativeRows.map((row, idx) => (
426
  <tr key={idx} className="hover:bg-muted/20">
427
  <td className="px-3 py-1.5 text-muted-foreground">{idx + 1}</td>
428
+ <td className="px-3 py-1.5">{formatMetricName(row.metric)}</td>
429
  <td className="px-3 py-1.5 text-right font-medium">{row.value}</td>
430
  <td className="px-3 py-1.5 text-muted-foreground">{row.dataType}</td>
431
  <td className="px-3 py-1.5 text-muted-foreground">{row.asOf}</td>