Jaspers Hub

biseroff / massive

pluginReviewed★ 0↓ 4

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.4 KB
1import { definePlugin, defineView } from '@jaspers-ai/sdk'
2import { z } from 'zod'
3import { barSources } from './stocks-bars'
4import { snapSources } from './stocks-snap'
5import { tickSources } from './ticks'
6import { referenceSources } from './reference'
7import { news } from './news'
8import { financials } from './financials'
9import { optionSources } from './options'
10import { globalSources } from './global'
11import { indicator } from './indicators'
12import { selfCheck } from './selfcheck'
13import { NewsView } from './NewsView'
14import { PriceView } from './PriceView'
15import { WatchlistView } from './WatchlistView'
16import { ChainView } from './ChainView'
17
18const sources = {
19 ...barSources,
20 ...snapSources,
21 ...tickSources,
22 ...referenceSources,
23 news,
24 financials,
25 ...optionSources,
26 ...globalSources,
27 indicator,
28 'self-check': selfCheck,
29}
30
31export default definePlugin({
32 id: 'massive',
33 secrets: { apikey: { label: 'Massive (Polygon.io) API key' } },
34 sources,
35 views: {
36 watchlist: defineView(WatchlistView, {
37 title: 'Massive watchlist',
38 state: z.object({
39 tickers: z.array(z.string()).max(100).default(['AAPL', 'MSFT', 'NVDA']).describe('Stock tickers to show.'),
40 }),
41 output: z.object({ tickers: z.array(z.string()), count: z.number(), error: z.string().nullable() }),
42 instructions: 'A snapshot table of stocks: last, change, change %, volume. Set state.tickers to the tickers; the user refreshes it with its button.',
43 renders: [snapSources.snapshot],
44 summarize: (state, output) => `Watchlist: ${output.count} of ${state.tickers?.length ?? 0} tickers`,
45 }),
46 chart: defineView(PriceView, {
47 title: 'Massive price chart',
48 state: z.object({
49 ticker: z.string().default('AAPL').describe('Any ticker: AAPL, O:..., I:SPX, C:EURUSD, X:BTCUSD.'),
50 multiplier: z.number().int().min(1).default(1).describe('Timespans per bar.'),
51 timespan: z.enum(['minute', 'hour', 'day', 'week', 'month', 'quarter', 'year']).default('day').describe('Bar size.'),
52 from: z.string().optional().describe('Start date YYYY-MM-DD. Defaults to six months ago.'),
53 to: z.string().optional().describe('End date YYYY-MM-DD. Defaults to today.'),
54 style: z.enum(['candles', 'line']).default('candles').describe('Candlesticks or a close line.'),
55 }),
56 output: z.object({ ticker: z.string(), bars: z.number(), first: z.string().nullable(), last: z.string().nullable(), close: z.number().nullable(), error: z.string().nullable() }),
57 instructions: 'A candlestick or line chart with volume bars from Massive aggregates. Set state.ticker, and optionally multiplier, timespan, from, to, style.',
58 renders: [barSources.aggregates],
59 summarize: (state, output) => `${state.ticker ?? 'AAPL'} chart: ${output.bars} bars, last close ${output.close ?? '–'}`,
60 }),
61 chain: defineView(ChainView, {
62 title: 'Massive option chain',
63 state: z.object({
64 underlying: z.string().default('SPY').describe('The underlying ticker.'),
65 expiration: z.string().optional().describe('Expiration YYYY-MM-DD. Defaults to the nearest one.'),
66 strike_min: z.number().optional().describe('Lowest strike shown.'),
67 strike_max: z.number().optional().describe('Highest strike shown.'),
68 }),
69 output: z.object({ underlying: z.string(), expiration: z.string().nullable(), strikes: z.number(), underlyingPrice: z.number().nullable(), error: z.string().nullable() }),
70 instructions: 'Calls and puts side by side by strike for one underlying and expiration. Set state.underlying, state.expiration, and a strike range.',
71 renders: [optionSources['option-chain']],
72 summarize: (state, output) => `${state.underlying ?? 'SPY'} chain ${output.expiration ?? ''}: ${output.strikes} strikes`,
73 }),
74 news: defineView(NewsView, {
75 title: 'Massive news',
76 state: z.object({
77 tickers: z.array(z.string()).max(20).default(['AAPL']).describe('Tickers whose news to list.'),
78 limit: z.number().int().min(1).max(200).default(50).describe('How many articles.'),
79 }),
80 output: z.object({ tickers: z.array(z.string()), count: z.number(), latest: z.string().nullable(), error: z.string().nullable() }),
81 instructions: 'Ticker news from Massive, newest first, with publisher, time, link, summary, and sentiment. Set state.tickers and state.limit.',
82 renders: [news],
83 summarize: (state, output) => `News for ${(state.tickers ?? []).join(', ')}: ${output.count} articles`,
84 }),
85 },
86})