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.4 KB
1import { defineSource } from '@jaspers-ai/sdk'
2import { z } from 'zod'
3import { HOSTS, baseField, get, iso, type Params } from './client'
4
5// Technical indicators Massive computes: SMA, EMA, RSI, MACD, newest first.
6
7export const indicator = defineSource({
8 description:
9 'A technical indicator for any ticker, newest first: time (ISO) and value; MACD adds signal and histogram. SMA, EMA, RSI, or MACD over day/hour/minute bars.',
10 hosts: HOSTS,
11 input: z.object({
12 ticker: z.string().min(1).describe('A ticker of any asset class, like AAPL or X:BTCUSD.'),
13 indicator: z.enum(['sma', 'ema', 'rsi', 'macd']).default('sma').describe('sma, ema, rsi, or macd.'),
14 timespan: z.enum(['minute', 'hour', 'day', 'week', 'month', 'quarter', 'year']).default('day').describe('The bar size.'),
15 window: z.number().int().min(1).default(14).describe('The window for sma, ema, rsi, like 50 for a 50-day SMA.'),
16 short_window: z.number().int().min(1).default(12).describe('MACD short EMA window.'),
17 long_window: z.number().int().min(1).default(26).describe('MACD long EMA window.'),
18 signal_window: z.number().int().min(1).default(9).describe('MACD signal window.'),
19 series_type: z.enum(['open', 'high', 'low', 'close']).default('close').describe('Which price to compute on.'),
20 from: z.string().optional().describe('Earliest date, YYYY-MM-DD.'),
21 to: z.string().optional().describe('Latest date, YYYY-MM-DD.'),
22 adjusted: z.boolean().default(true).describe('Adjust for splits.'),
23 limit: z.number().int().min(1).max(5000).default(250).describe('Most values to answer.'),
24 base: baseField,
25 }),
26 async run(args, ctx) {
27 const t = args.ticker.trim().toUpperCase()
28 const windows: Params =
29 args.indicator === 'macd'
30 ? { short_window: args.short_window, long_window: args.long_window, signal_window: args.signal_window }
31 : { window: args.window }
32 const body = await get(ctx, args.base, `/v1/indicators/${args.indicator}/${t}`, {
33 timespan: args.timespan,
34 series_type: args.series_type,
35 adjusted: args.adjusted,
36 'timestamp.gte': args.from,
37 'timestamp.lte': args.to,
38 order: 'desc',
39 limit: args.limit,
40 ...windows,
41 })
42 const values = (body?.results?.values ?? []) as any[]
43 return values.map((v) => ({
44 ticker: t,
45 indicator: args.indicator,
46 time: iso(v.timestamp),
47 value: v.value ?? null,
48 ...(args.indicator === 'macd' ? { signal: v.signal ?? null, histogram: v.histogram ?? null } : {}),
49 }))
50 },
51})