Spaces:
Sleeping
Sleeping
Fix: Add units to metric values (%, x suffix)
Browse filesMetrics now display with appropriate units:
- Percentages (margins, growth rates, inflation): 3.18%
- Ratios (P/E, P/B, Beta, etc.): 12.14x
- Currency (revenue, market cap): $185.0B
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
frontend/src/components/MCPDataPanel.tsx
CHANGED
|
@@ -81,13 +81,58 @@ function formatMetricName(metric: string): string {
|
|
| 81 |
.join(' ')
|
| 82 |
}
|
| 83 |
|
| 84 |
-
//
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
if (value === null || value === undefined) return '—'
|
| 87 |
-
|
| 88 |
if (typeof value === 'string') return value
|
| 89 |
|
| 90 |
const num = value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
if (Math.abs(num) >= 1e12) return `$${(num / 1e12).toFixed(1)}T`
|
| 92 |
if (Math.abs(num) >= 1e9) return `$${(num / 1e9).toFixed(1)}B`
|
| 93 |
if (Math.abs(num) >= 1e6) return `$${(num / 1e6).toFixed(1)}M`
|
|
@@ -210,7 +255,7 @@ export function MCPDataPanel({ metrics, rawData, companyName, ticker, exchange,
|
|
| 210 |
for (const m of groupedMetrics[cat] || []) {
|
| 211 |
rows.push({
|
| 212 |
metric: m.metric,
|
| 213 |
-
value: formatValue(m.value),
|
| 214 |
dataType: inferDataType(m.form, m.metric),
|
| 215 |
asOf: m.endDate || '-',
|
| 216 |
source: inferDataSource(cat, m.metric, m.form, m.dataSource),
|
|
|
|
| 81 |
.join(' ')
|
| 82 |
}
|
| 83 |
|
| 84 |
+
// Metrics that should display as percentages
|
| 85 |
+
const PERCENTAGE_METRICS = new Set([
|
| 86 |
+
'net_margin_pct', 'gross_margin_pct', 'operating_margin_pct',
|
| 87 |
+
'net_margin', 'gross_margin', 'operating_margin',
|
| 88 |
+
'revenue_growth', 'earnings_growth',
|
| 89 |
+
'gdp_growth', 'cpi_inflation', 'inflation', 'unemployment', 'interest_rate',
|
| 90 |
+
'historical_volatility', 'implied_volatility', 'hist_vol'
|
| 91 |
+
])
|
| 92 |
+
|
| 93 |
+
// Metrics that should display as ratios (x suffix)
|
| 94 |
+
const RATIO_METRICS = new Set([
|
| 95 |
+
'trailing_pe', 'forward_pe', 'pb_ratio', 'ps_ratio', 'trailing_peg',
|
| 96 |
+
'price_to_fcf', 'ev_ebitda', 'ev_revenue', 'debt_to_equity', 'beta',
|
| 97 |
+
'p/e', 'p/b', 'p/s', 'peg'
|
| 98 |
+
])
|
| 99 |
+
|
| 100 |
+
// Metrics that are currency values (large numbers get $B/$M formatting)
|
| 101 |
+
const CURRENCY_METRICS = new Set([
|
| 102 |
+
'revenue', 'net_income', 'gross_profit', 'operating_income',
|
| 103 |
+
'free_cash_flow', 'operating_cash_flow', 'total_assets', 'total_liabilities',
|
| 104 |
+
'stockholders_equity', 'cash', 'long_term_debt', 'net_debt', 'rd_expense',
|
| 105 |
+
'market_cap', 'enterprise_value'
|
| 106 |
+
])
|
| 107 |
+
|
| 108 |
+
// Format numbers for display with appropriate units
|
| 109 |
+
function formatValue(value: string | number, metric?: string): string {
|
| 110 |
if (value === null || value === undefined) return '—'
|
|
|
|
| 111 |
if (typeof value === 'string') return value
|
| 112 |
|
| 113 |
const num = value
|
| 114 |
+
const lowerMetric = (metric || '').toLowerCase()
|
| 115 |
+
|
| 116 |
+
// Check if this is a percentage metric
|
| 117 |
+
if (PERCENTAGE_METRICS.has(lowerMetric)) {
|
| 118 |
+
return `${num.toFixed(2)}%`
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
// Check if this is a ratio metric
|
| 122 |
+
if (RATIO_METRICS.has(lowerMetric)) {
|
| 123 |
+
return `${num.toFixed(2)}x`
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
// Check if this is a currency metric (large numbers)
|
| 127 |
+
if (CURRENCY_METRICS.has(lowerMetric)) {
|
| 128 |
+
if (Math.abs(num) >= 1e12) return `$${(num / 1e12).toFixed(1)}T`
|
| 129 |
+
if (Math.abs(num) >= 1e9) return `$${(num / 1e9).toFixed(1)}B`
|
| 130 |
+
if (Math.abs(num) >= 1e6) return `$${(num / 1e6).toFixed(1)}M`
|
| 131 |
+
if (Math.abs(num) >= 1e3) return `$${(num / 1e3).toFixed(1)}K`
|
| 132 |
+
return `$${num.toFixed(2)}`
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
// Default formatting for other metrics
|
| 136 |
if (Math.abs(num) >= 1e12) return `$${(num / 1e12).toFixed(1)}T`
|
| 137 |
if (Math.abs(num) >= 1e9) return `$${(num / 1e9).toFixed(1)}B`
|
| 138 |
if (Math.abs(num) >= 1e6) return `$${(num / 1e6).toFixed(1)}M`
|
|
|
|
| 255 |
for (const m of groupedMetrics[cat] || []) {
|
| 256 |
rows.push({
|
| 257 |
metric: m.metric,
|
| 258 |
+
value: formatValue(m.value, m.metric),
|
| 259 |
dataType: inferDataType(m.form, m.metric),
|
| 260 |
asOf: m.endDate || '-',
|
| 261 |
source: inferDataSource(cat, m.metric, m.form, m.dataSource),
|