Consolidate metric definitions with Rust JSON as single source of truth

- Add core.computed.json with 32 ratio definitions (filing + market derived)
- Add Rust types for ComputedDefinition and ComputationSpec
- Create generate-taxonomy.ts to generate TypeScript from Rust JSON
- Generate lib/generated/ (gitignored) with surfaces, computed, kpis
- Update financial-metrics.ts to use generated definitions
- Add build-time generation via 'bun run generate'
- Add taxonomy architecture documentation

Two-phase ratio computation:
- Filing-derived: margins, returns, per-share, growth (Rust computes)
- Market-derived: valuation ratios (TypeScript computes with price data)

All 32 ratios defined in core.computed.json:
- Margins: gross, operating, ebitda, net, fcf
- Returns: roa, roe, roic, roce
- Financial health: debt_to_equity, net_debt_to_ebitda, cash_to_debt, current_ratio
- Per-share: revenue, fcf, book_value
- Growth: yoy metrics + 3y/5y cagr
- Valuation: market_cap, ev, p/e, p/fcf, p/b, ev/sales, ev/ebitda, ev/fcf
This commit is contained in:
2026-03-15 15:22:51 -04:00
parent ed4420b8db
commit 24aa8e33d4
11 changed files with 1453 additions and 123 deletions

View File

@@ -3,10 +3,10 @@ import type {
FinancialUnit
} from '@/lib/types';
import {
BALANCE_SHEET_METRIC_DEFINITIONS,
CASH_FLOW_STATEMENT_METRIC_DEFINITIONS,
INCOME_STATEMENT_METRIC_DEFINITIONS
} from '@/lib/financial-metrics';
INCOME_SURFACES,
BALANCE_SURFACES,
CASH_FLOW_SURFACES
} from '@/lib/generated';
export type CanonicalRowDefinition = {
key: string;
@@ -14,12 +14,20 @@ export type CanonicalRowDefinition = {
category: string;
order: number;
unit: FinancialUnit;
localNames?: readonly string[];
labelIncludes?: readonly string[];
};
function toCanonicalRow(surface: { surface_key: string; label: string; category: string; order: number; unit: string }) {
return {
key: surface.surface_key,
label: surface.label,
category: surface.category,
order: surface.order,
unit: surface.unit as FinancialUnit
};
}
export const CANONICAL_ROW_DEFINITIONS: Record<Extract<FinancialStatementKind, 'income' | 'balance' | 'cash_flow'>, CanonicalRowDefinition[]> = {
income: INCOME_STATEMENT_METRIC_DEFINITIONS,
balance: BALANCE_SHEET_METRIC_DEFINITIONS,
cash_flow: CASH_FLOW_STATEMENT_METRIC_DEFINITIONS
income: INCOME_SURFACES.map(toCanonicalRow),
balance: BALANCE_SURFACES.map(toCanonicalRow),
cash_flow: CASH_FLOW_SURFACES.map(toCanonicalRow)
};

View File

@@ -5,7 +5,7 @@ import type {
StandardizedFinancialRow
} from '@/lib/types';
import {
RATIO_CATEGORY_ORDER,
RATIO_CATEGORIES,
RATIO_DEFINITIONS
} from '@/lib/financial-metrics';

View File

@@ -5,7 +5,7 @@ import type {
StructuredKpiRow,
TrendSeries
} from '@/lib/types';
import { RATIO_CATEGORY_ORDER } from '@/lib/financial-metrics';
import { RATIO_CATEGORIES } from '@/lib/generated';
import { KPI_CATEGORY_ORDER } from '@/lib/server/financials/kpi-registry';
function toTrendSeriesRow(row: {
@@ -31,7 +31,7 @@ export function buildFinancialCategories(rows: Array<{ category: string }>, surf
}
const order = surfaceKind === 'ratios'
? [...RATIO_CATEGORY_ORDER]
? [...RATIO_CATEGORIES]
: surfaceKind === 'segments_kpis'
? [...KPI_CATEGORY_ORDER]
: [...counts.keys()];