Jaspers Hub

biseroff / massive

pluginReviewed★ 0↓ 3

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.

4.3 KB
1import { defineSource } from '@jaspers-ai/sdk'
2import { z } from 'zod'
3import { HOSTS, bar, baseField, daysAgo, get, list, upper } from './client'
4
5// Bars: aggregates for any asset class, previous close, the grouped market day, one day's open/close.
6
7const ticker = z.string().min(1).describe('A ticker: AAPL for a stock, O:SPY251219C00600000 an option, I:SPX an index, C:EURUSD forex, X:BTCUSD crypto.')
8
9const aggregates = defineSource({
10 description:
11 'Aggregate bars for any ticker (stocks, options O:, indices I:, forex C:, crypto X:) over a date range: time (ISO), open, high, low, close, volume, vwap, transactions. Newest first by default.',
12 hosts: HOSTS,
13 input: z.object({
14 ticker,
15 multiplier: z.number().int().min(1).default(1).describe('How many timespans make one bar, like 5 with minute for 5-minute bars.'),
16 timespan: z.enum(['second', 'minute', 'hour', 'day', 'week', 'month', 'quarter', 'year']).default('day').describe('The bar size unit.'),
17 from: z.string().optional().describe('Start date YYYY-MM-DD or a millisecond timestamp. Defaults to one year ago.'),
18 to: z.string().optional().describe('End date YYYY-MM-DD or a millisecond timestamp. Defaults to today.'),
19 adjusted: z.boolean().default(true).describe('Adjust for splits.'),
20 sort: z.enum(['asc', 'desc']).default('desc').describe('desc for newest first, asc for oldest first.'),
21 limit: z.number().int().min(1).max(50000).default(5000).describe('Most bars to answer.'),
22 base: baseField,
23 }),
24 async run(args, ctx) {
25 const t = upper(args.ticker)
26 const from = args.from ?? daysAgo(365)
27 const to = args.to ?? daysAgo(0)
28 const path = `/v2/aggs/ticker/${t}/range/${args.multiplier}/${args.timespan}/${from}/${to}`
29 const res = await list(ctx, args.base, path, { adjusted: args.adjusted, sort: args.sort, limit: args.limit }, args.limit)
30 return { rows: res.rows.map((b) => bar(b, t)), ticker: t, from, to, more: res.more, pages: res.pages }
31 },
32})
33
34const previousClose = defineSource({
35 description: "The previous trading day's bar for a ticker (any asset class): open, high, low, close, volume, vwap.",
36 hosts: HOSTS,
37 input: z.object({ ticker, adjusted: z.boolean().default(true).describe('Adjust for splits.'), base: baseField }),
38 async run(args, ctx) {
39 const t = upper(args.ticker)
40 const body = await get(ctx, args.base, `/v2/aggs/ticker/${t}/prev`, { adjusted: args.adjusted })
41 return ((body?.results ?? []) as any[]).map((b) => bar(b, t))
42 },
43})
44
45const groupedDaily = defineSource({
46 description: 'Daily bars for every US stock on one date, highest volume first: ticker, open, high, low, close, volume, vwap, transactions.',
47 hosts: HOSTS,
48 input: z.object({
49 date: z.string().describe('The trading date, YYYY-MM-DD.'),
50 adjusted: z.boolean().default(true).describe('Adjust for splits.'),
51 include_otc: z.boolean().default(false).describe('Include OTC securities.'),
52 limit: z.number().int().min(1).max(15000).default(1000).describe('Most rows to answer, by volume.'),
53 base: baseField,
54 }),
55 async run(args, ctx) {
56 const body = await get(ctx, args.base, `/v2/aggs/grouped/locale/us/market/stocks/${args.date}`, {
57 adjusted: args.adjusted,
58 include_otc: args.include_otc,
59 })
60 const bars = ((body?.results ?? []) as any[]).sort((a, b) => (b.v ?? 0) - (a.v ?? 0))
61 return { rows: bars.slice(0, args.limit).map((b) => bar(b)), date: args.date, total: bars.length }
62 },
63})
64
65const dailyOpenClose = defineSource({
66 description: 'Open, high, low, close, volume, pre-market and after-hours prices for one ticker on one date.',
67 hosts: HOSTS,
68 input: z.object({
69 ticker,
70 date: z.string().describe('The date, YYYY-MM-DD.'),
71 adjusted: z.boolean().default(true).describe('Adjust for splits.'),
72 base: baseField,
73 }),
74 async run(args, ctx) {
75 const t = upper(args.ticker)
76 const b = await get(ctx, args.base, `/v1/open-close/${t}/${args.date}`, { adjusted: args.adjusted })
77 return [
78 {
79 ticker: b.symbol ?? t,
80 date: b.from ?? args.date,
81 open: b.open ?? null,
82 high: b.high ?? null,
83 low: b.low ?? null,
84 close: b.close ?? null,
85 volume: b.volume ?? null,
86 preMarket: b.preMarket ?? null,
87 afterHours: b.afterHours ?? null,
88 },
89 ]
90 },
91})
92
93export const barSources = {
94 aggregates,
95 'previous-close': previousClose,
96 'grouped-daily': groupedDaily,
97 'daily-open-close': dailyOpenClose,
98}