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.

2.8 KB
1import { defineSource } from '@jaspers-ai/sdk'
2import { z } from 'zod'
3import { HOSTS, baseField, iso, list, upper, type Params } from './client'
4
5// Tick data: trades and quotes for a stock or option ticker, newest first.
6
7const input = z.object({
8 ticker: z.string().min(1).describe('A stock ticker like AAPL, or an option like O:SPY251219C00600000.'),
9 date: z.string().optional().describe('One day, YYYY-MM-DD. Leave out to use the timestamp bounds or the latest data.'),
10 from: z.string().optional().describe('Earliest timestamp, ISO date-time or nanoseconds (timestamp.gte).'),
11 to: z.string().optional().describe('Latest timestamp, ISO date-time or nanoseconds (timestamp.lte).'),
12 order: z.enum(['asc', 'desc']).default('desc').describe('desc for newest first.'),
13 limit: z.number().int().min(1).max(50000).default(1000).describe('Most rows to answer.'),
14 base: baseField,
15})
16
17type Args = z.infer<typeof input>
18
19function params(args: Args): Params {
20 return {
21 timestamp: args.date,
22 'timestamp.gte': args.from,
23 'timestamp.lte': args.to,
24 order: args.order,
25 sort: 'timestamp',
26 limit: Math.min(args.limit, 50000),
27 }
28}
29
30const joined = (v: unknown) => (Array.isArray(v) ? v.join(', ') : null)
31
32const trades = defineSource({
33 description: 'Trades for a ticker: time, price, size, exchange, conditions, tape, sequence number. Newest first.',
34 hosts: HOSTS,
35 input,
36 async run(args, ctx) {
37 const t = upper(args.ticker)
38 const res = await list(ctx, args.base, `/v3/trades/${t}`, params(args), args.limit)
39 const rows = res.rows.map((r) => ({
40 ticker: t,
41 time: iso(r.sip_timestamp ?? r.participant_timestamp),
42 price: r.price ?? null,
43 size: r.size ?? null,
44 exchange: r.exchange ?? null,
45 conditions: joined(r.conditions),
46 tape: r.tape ?? null,
47 sequence_number: r.sequence_number ?? null,
48 id: r.id ?? null,
49 }))
50 return { rows, more: res.more, pages: res.pages }
51 },
52})
53
54const quotes = defineSource({
55 description: 'NBBO quotes for a ticker: time, bid, bid size, ask, ask size, exchanges, conditions. Newest first.',
56 hosts: HOSTS,
57 input,
58 async run(args, ctx) {
59 const t = upper(args.ticker)
60 const res = await list(ctx, args.base, `/v3/quotes/${t}`, params(args), args.limit)
61 const rows = res.rows.map((r) => ({
62 ticker: t,
63 time: iso(r.sip_timestamp ?? r.participant_timestamp),
64 bid: r.bid_price ?? null,
65 bid_size: r.bid_size ?? null,
66 bid_exchange: r.bid_exchange ?? null,
67 ask: r.ask_price ?? null,
68 ask_size: r.ask_size ?? null,
69 ask_exchange: r.ask_exchange ?? null,
70 conditions: joined(r.conditions),
71 tape: r.tape ?? null,
72 sequence_number: r.sequence_number ?? null,
73 }))
74 return { rows, more: res.more, pages: res.pages }
75 },
76})
77
78export const tickSources = { trades, quotes }