Massive Market Data (Polygon.io): Market data plugin wrapping the Polygon.io/Massive REST API: bars, snapshots, options, news, financials, indicators, and four chart/watchlist views.
| 1 | import { defineSource } from '@jaspers-ai/sdk' |
| 2 | import { z } from 'zod' |
| 3 | import { HOSTS, baseField, list, upper, type Row } from './client' |
| 4 | |
| 5 | // Fundamentals from SEC filings: one row per period, every income statement, balance sheet, cash flow, |
| 6 | // and comprehensive income line as a column like income_statement_revenues. |
| 7 | |
| 8 | export const financials = defineSource({ |
| 9 | description: |
| 10 | '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.', |
| 11 | hosts: HOSTS, |
| 12 | input: z.object({ |
| 13 | ticker: z.string().min(1).describe('The ticker, like AAPL.'), |
| 14 | timeframe: z.enum(['annual', 'quarterly', 'ttm']).default('quarterly').describe('annual, quarterly, or ttm (trailing twelve months).'), |
| 15 | limit: z.number().int().min(1).max(100).default(8).describe('How many periods.'), |
| 16 | base: baseField, |
| 17 | }), |
| 18 | async run(args, ctx) { |
| 19 | const ticker = upper(args.ticker) |
| 20 | const res = await list( |
| 21 | ctx, |
| 22 | args.base, |
| 23 | '/vX/reference/financials', |
| 24 | { ticker, timeframe: args.timeframe, order: 'desc', sort: 'period_of_report_date', limit: Math.min(args.limit, 100) }, |
| 25 | args.limit, |
| 26 | ) |
| 27 | const rows = res.rows.map((p) => { |
| 28 | const row: Row = { |
| 29 | ticker, |
| 30 | company_name: p.company_name ?? null, |
| 31 | fiscal_year: p.fiscal_year ?? null, |
| 32 | fiscal_period: p.fiscal_period ?? null, |
| 33 | timeframe: p.timeframe ?? null, |
| 34 | start_date: p.start_date ?? null, |
| 35 | end_date: p.end_date ?? null, |
| 36 | filing_date: p.filing_date ?? null, |
| 37 | } |
| 38 | // Each section is { line: { value, unit, label, order } }: keep the values, one column a line. |
| 39 | for (const [section, lines] of Object.entries((p.financials ?? {}) as Record<string, any>)) |
| 40 | for (const [line, item] of Object.entries((lines ?? {}) as Record<string, any>)) |
| 41 | row[`${section}_${line}`] = typeof item?.value === 'number' ? item.value : null |
| 42 | return row |
| 43 | }) |
| 44 | return { rows, more: res.more } |
| 45 | }, |
| 46 | }) |