import { defineSource } from '@jaspers-ai/sdk' import { z } from 'zod' import { HOST, benzingaGet, calendarParams, calendarRows, num, str } from './client' const tickers = z.string().optional().describe('Comma-separated tickers, like AAPL,MSFT.') const page = z.number().int().min(0).default(0).describe('Page number, from 0.') const pagesize = z.number().int().min(1).max(1000).default(100).describe('Rows per page, up to 1000.') /** Newest date and time first. */ const newestFirst = (a: { date: string | null; time: string | null }, b: { date: string | null; time: string | null }) => `${b.date ?? ''}${b.time ?? ''}`.localeCompare(`${a.date ?? ''}${a.time ?? ''}`) export const ratings = defineSource({ description: 'Benzinga analyst ratings: upgrades, downgrades, initiations, price target changes. Default the last 30 days, newest first. Rows: date, time, ticker, name, analyst (firm), analyst_name, action_company, action_pt, rating_current, rating_prior, pt_current, pt_prior, importance, url.', hosts: [HOST], input: z.object({ tickers, date_from: z.string().optional().describe('Start date YYYY-MM-DD. Default 30 days ago.'), date_to: z.string().optional().describe('End date YYYY-MM-DD. Default today.'), action: z .string() .optional() .describe('Filter on action_company: Upgrades, Downgrades, Maintains, Initiates Coverage On, Reiterates, Terminates Coverage On, and the like.'), importance: z.number().int().min(0).max(5).optional().describe('Minimum importance, 0 to 5.'), page, pagesize, }), async run(args, ctx) { const body = await benzingaGet(ctx, 'ratings', '/api/v2.1/calendar/ratings', { ...calendarParams(args, 30, 0), 'parameters[action]': args.action, 'parameters[importance]': args.importance, }) return calendarRows(body, 'ratings') .map((r) => ({ date: str(r.date), time: str(r.time), ticker: str(r.ticker), name: str(r.name), analyst: str(r.analyst), analyst_name: str(r.analyst_name), action_company: str(r.action_company), action_pt: str(r.action_pt), rating_current: str(r.rating_current), rating_prior: str(r.rating_prior), pt_current: num(r.pt_current), pt_prior: num(r.pt_prior), importance: num(r.importance), url: str(r.url) ?? str(r.url_news), })) .sort(newestFirst) }, }) export const earnings = defineSource({ description: 'Benzinga earnings calendar. Default 7 days back to 14 ahead. Rows: date, time, ticker, name, period, period_year, eps_est, eps, eps_prior, eps_surprise, revenue_est, revenue, revenue_prior, revenue_surprise, importance.', hosts: [HOST], input: z.object({ tickers, date_from: z.string().optional().describe('Start date YYYY-MM-DD. Default 7 days ago.'), date_to: z.string().optional().describe('End date YYYY-MM-DD. Default 14 days ahead.'), page, pagesize, }), async run(args, ctx) { const body = await benzingaGet(ctx, 'earnings', '/api/v2.1/calendar/earnings', calendarParams(args, 7, 14)) return calendarRows(body, 'earnings') .map((r) => ({ date: str(r.date), time: str(r.time), ticker: str(r.ticker), name: str(r.name), period: str(r.period), period_year: num(r.period_year), eps_est: num(r.eps_est), eps: num(r.eps), eps_prior: num(r.eps_prior), eps_surprise: num(r.eps_surprise), revenue_est: num(r.revenue_est), revenue: num(r.revenue), revenue_prior: num(r.revenue_prior), revenue_surprise: num(r.revenue_surprise), importance: num(r.importance), })) .sort(newestFirst) }, }) export const guidance = defineSource({ description: 'Benzinga company guidance, newest first. Default the last 90 days. Rows: date, time, ticker, name, period, period_year, prelim, eps_guidance_min/max, eps_guidance_prior_min/max, eps_guidance_est, revenue_guidance_min/max, revenue_guidance_prior_min/max, revenue_guidance_est, importance.', hosts: [HOST], input: z.object({ tickers, date_from: z.string().optional().describe('Start date YYYY-MM-DD. Default 90 days ago.'), date_to: z.string().optional().describe('End date YYYY-MM-DD. Default today.'), page, pagesize, }), async run(args, ctx) { const body = await benzingaGet(ctx, 'guidance', '/api/v2.1/calendar/guidance', calendarParams(args, 90, 0)) return calendarRows(body, 'guidance') .map((r) => ({ date: str(r.date), time: str(r.time), ticker: str(r.ticker), name: str(r.name), period: str(r.period), period_year: num(r.period_year), prelim: str(r.prelim), eps_guidance_min: num(r.eps_guidance_min), eps_guidance_max: num(r.eps_guidance_max), eps_guidance_prior_min: num(r.eps_guidance_prior_min), eps_guidance_prior_max: num(r.eps_guidance_prior_max), eps_guidance_est: num(r.eps_guidance_est), revenue_guidance_min: num(r.revenue_guidance_min), revenue_guidance_max: num(r.revenue_guidance_max), revenue_guidance_prior_min: num(r.revenue_guidance_prior_min), revenue_guidance_prior_max: num(r.revenue_guidance_prior_max), revenue_guidance_est: num(r.revenue_guidance_est), importance: num(r.importance), })) .sort(newestFirst) }, })