Jaspers Hub

biseroff / charts

pluginReviewed★ 0↓ 0

Charts: Interactive price chart view with lines or candles and volume, backed by Yahoo, Massive, or Databento bar data.

2.8 KB
1import { definePlugin, defineSource, defineView } from '@jaspers-ai/sdk'
2import { z } from 'zod'
3import { ChartView } from './ChartView'
4import { DEFAULT_SYMBOLS, INTERVALS } from './plan'
5
6// The yfinance plugin's MCP connection, its history tool: the chart's price feed.
7const history = defineSource({
8 mcp: 'yfinance/server',
9 tool: 'get_price_history',
10 description:
11 "Yahoo Finance price bars for one symbol (the yfinance plugin's history tool), as the charts view reads them.",
12 ttlMs: 60_000,
13})
14
15export default definePlugin({
16 id: 'charts',
17 title: 'Charts',
18 description:
19 'Interactive price chart: Yahoo, Massive or Databento bars; lines or candles, volume, 1m–1wk, zoom/pan like TradingView',
20 sources: { history },
21 views: {
22 chart: defineView(ChartView, {
23 title: 'Price chart',
24 state: z.object({
25 symbols: z.array(z.string()).max(30).default(DEFAULT_SYMBOLS).describe('Ticker symbols shown, like AAPL.'),
26 interval: z.enum(INTERVALS).default('1d').describe('Bar size.'),
27 mode: z.enum(['lines', 'candles']).default('lines').describe('lines: % change of every symbol; candles: the active symbol.'),
28 active: z.string().nullable().default(null).describe('The highlighted symbol (candles and volume); null means the first.'),
29 volume: z.boolean().default(true).describe('Show the volume pane.'),
30 source: z
31 .enum(['yahoo', 'massive', 'databento'])
32 .default('yahoo')
33 .describe('Where the bars come from: yahoo (yfinance plugin), massive (massive plugin, delayed), databento (databento plugin, DBEQ.BASIC daily bars from 2023-03; 1d and 1wk only).'),
34 }),
35 output: z.object({
36 symbols: z.array(z.string()),
37 source: z.string().optional(),
38 interval: z.string(),
39 mode: z.string(),
40 active: z.string().nullable(),
41 loaded: z.array(z.string()),
42 failed: z.array(z.string()),
43 price: z
44 .object({
45 series: z.number(),
46 points: z.number(),
47 finite: z.boolean(),
48 pane: z.number().nullable(),
49 volumePane: z.number().nullable(),
50 })
51 .nullable()
52 .optional(),
53 }),
54 instructions:
55 'An interactive price chart. Set state.source (yahoo, massive, or databento; databento has 1d and 1wk only and no indices), state.symbols, state.interval (1m, 2m, 5m, 15m, 30m, 1h, 1d, 1wk), state.mode (lines or candles), state.active (the symbol drawn in candles and whose volume shows), and state.volume. The user changes all of these in the view too; Massive loads symbols one at a time and waits out rate limits.',
56 renders: [history],
57 summarize: (state, output) =>
58 `Chart ${state.source ?? 'yahoo'} ${state.interval ?? '1d'} ${state.mode ?? 'lines'}: ${(state.symbols ?? []).join(', ')}${output.failed?.length ? ` (failed: ${output.failed.join(', ')})` : ''}`,
59 }),
60 },
61})