Jaspers Hub

biseroff / option-chain

pluginReviewed★ 0↓ 0

Options Chain: Shows a multi-vendor options chain straddle table with IV, delta, OI, volume, and max pain for a ticker.

3.1 KB
1import { definePlugin, defineSource, defineView } from '@jaspers-ai/sdk'
2import { z } from 'zod'
3import { TableView } from './src/TableView.tsx'
4import { fetchYahooChain } from './src/yahoo.ts'
5
6const chain = defineSource({
7 description:
8 'Yahoo Finance options chain straddle table (Calls & Puts side-by-side per strike) for a ticker symbol. Returns underlying spot price, available expirations, summary metrics (ATM IV, ATM straddle, put/call OI & volume ratios, max pain), and strike rows with Bid, Ask, Last, Volume, Open Interest, Implied Volatility %, and Black-Scholes Delta.',
9 hosts: [],
10 input: z.object({
11 symbol: z.string().min(1).default('FLWS').describe('Underlying stock/ETF ticker symbol, like FLWS, WEN, or SPY.'),
12 expiration: z
13 .string()
14 .optional()
15 .describe('Expiration date in YYYY-MM-DD format. Omit for the nearest expiration.'),
16 strikes: z
17 .number()
18 .int()
19 .min(0)
20 .max(200)
21 .default(20)
22 .describe('Number of strikes around ATM spot price to return (0 for all returned strikes).'),
23 }),
24 async run(args, ctx) {
25 return fetchYahooChain(ctx, args.symbol, args.expiration ?? undefined, args.strikes)
26 },
27})
28
29export default definePlugin({
30 id: 'option-chain',
31 capabilities: ['tools'],
32 sources: { chain },
33 views: {
34 table: defineView(TableView, {
35 title: 'Options Chain',
36 state: z.object({
37 symbol: z.string().default('FLWS').describe('Ticker symbol to show.'),
38 expiration: z
39 .string()
40 .nullable()
41 .optional()
42 .default(null)
43 .describe('Selected expiration date (YYYY-MM-DD), or null for nearest.'),
44 provider: z
45 .enum(['yahoo', 'alpaca', 'massive', 'databento'])
46 .default('yahoo')
47 .describe('Options data vendor: yahoo (default), alpaca, massive, or databento.'),
48 alpacaFeed: z
49 .enum(['indicative', 'opra'])
50 .default('indicative')
51 .describe('Alpaca options feed: indicative (free) or opra.'),
52 strikes: z.number().default(20).describe('Max strikes around ATM (10, 20, 40, or 0 for All).'),
53 }),
54 output: z.object({
55 symbol: z.string(),
56 provider: z.string(),
57 expiration: z.string().nullable(),
58 spot: z.number().nullable(),
59 strikeCount: z.number(),
60 expirationsCount: z.number(),
61 atmIv: z.number().nullable(),
62 atmStraddle: z.number().nullable(),
63 pcRatioOi: z.number().nullable(),
64 maxPain: z.number().nullable(),
65 }),
66 instructions:
67 'Interactive multi-vendor Options Chain straddle view. Set state.symbol (e.g. "FLWS", "WEN", "SPY"), state.provider ("yahoo" default, "alpaca", "massive", or "databento"), state.expiration ("YYYY-MM-DD" or null for nearest), and state.strikes (10, 20, 40, or 0 for All).',
68 renders: [chain],
69 summarize: (state, output) =>
70 `${output.symbol || state.symbol || 'FLWS'} (${output.provider || state.provider || 'yahoo'}) ${output.expiration ?? 'nearest'}: spot ${output.spot != null ? '$' + output.spot.toFixed(2) : '—'}, ${output.strikeCount ?? 0} strikes, ATM IV ${output.atmIv != null ? output.atmIv.toFixed(1) + '%' : '—'}`,
71 }),
72 },
73})