import { defineSource } from '@jaspers-ai/sdk' import { z } from 'zod' import { HOSTS, baseField, list, upper, type Row } from './client' // Fundamentals from SEC filings: one row per period, every income statement, balance sheet, cash flow, // and comprehensive income line as a column like income_statement_revenues. export const financials = defineSource({ description: 'Financial statements for a ticker, newest period first: one row per period (fiscal year, period, dates, filing date) with every income statement, balance sheet, and cash flow line as a column, like income_statement_revenues, balance_sheet_assets, cash_flow_statement_net_cash_flow_from_operating_activities.', hosts: HOSTS, input: z.object({ ticker: z.string().min(1).describe('The ticker, like AAPL.'), timeframe: z.enum(['annual', 'quarterly', 'ttm']).default('quarterly').describe('annual, quarterly, or ttm (trailing twelve months).'), limit: z.number().int().min(1).max(100).default(8).describe('How many periods.'), base: baseField, }), async run(args, ctx) { const ticker = upper(args.ticker) const res = await list( ctx, args.base, '/vX/reference/financials', { ticker, timeframe: args.timeframe, order: 'desc', sort: 'period_of_report_date', limit: Math.min(args.limit, 100) }, args.limit, ) const rows = res.rows.map((p) => { const row: Row = { ticker, company_name: p.company_name ?? null, fiscal_year: p.fiscal_year ?? null, fiscal_period: p.fiscal_period ?? null, timeframe: p.timeframe ?? null, start_date: p.start_date ?? null, end_date: p.end_date ?? null, filing_date: p.filing_date ?? null, } // Each section is { line: { value, unit, label, order } }: keep the values, one column a line. for (const [section, lines] of Object.entries((p.financials ?? {}) as Record)) for (const [line, item] of Object.entries((lines ?? {}) as Record)) row[`${section}_${line}`] = typeof item?.value === 'number' ? item.value : null return row }) return { rows, more: res.more } }, })