Jaspers Hub

jaspers / alpaca

pluginOfficialReviewed★ 0↓ 0

Alpaca: Alpaca brokerage plugin: stock/option market data, account, positions, orders, and order placement/cancellation, with watchlist, account, and blotter views.

4.1 KB
1import { definePlugin, defineView } from '@jaspers-ai/sdk'
2import { z } from 'zod'
3import { cancelOrder, confirmLiveOrder, placeOrder } from './actions'
4import { optionBars, optionChain, optionLatestQuote, optionLatestTrade, optionSnapshots, optionTrades } from './options'
5import { stockBars, stockLatestQuote, stockLatestTrade, stockQuotes, stockSnapshots, stockTrades } from './stocks'
6import { account, assets, orders, positions } from './trading'
7import { AccountPanel } from './views/AccountPanel'
8import { Blotter } from './views/Blotter'
9import { Watchlist } from './views/Watchlist'
10
11export default definePlugin({
12 id: 'alpaca',
13 capabilities: ['files'],
14 secrets: {
15 key_id: { label: 'Alpaca API key ID (paper account; also used for market data)' },
16 secret_key: { label: 'Alpaca API secret key (paper account; also used for market data)' },
17 live_key_id: { label: 'Alpaca LIVE account API key ID (only for live_account: true)', optional: true } as {
18 label: string
19 },
20 live_secret_key: { label: 'Alpaca LIVE account API secret key (only for live_account: true)', optional: true } as {
21 label: string
22 },
23 },
24 sources: {
25 'stock-bars': stockBars,
26 'stock-quotes': stockQuotes,
27 'stock-trades': stockTrades,
28 'stock-latest-quote': stockLatestQuote,
29 'stock-latest-trade': stockLatestTrade,
30 'stock-snapshots': stockSnapshots,
31 'option-bars': optionBars,
32 'option-trades': optionTrades,
33 'option-latest-quote': optionLatestQuote,
34 'option-latest-trade': optionLatestTrade,
35 'option-snapshots': optionSnapshots,
36 'option-chain': optionChain,
37 account,
38 positions,
39 orders,
40 assets,
41 'place-order': placeOrder,
42 'cancel-order': cancelOrder,
43 'confirm-live-order': confirmLiveOrder,
44 },
45 views: {
46 watchlist: defineView(Watchlist, {
47 title: 'Alpaca watchlist',
48 state: z.object({
49 symbols: z.array(z.string()).max(100).default(['AAPL', 'MSFT', 'NVDA']).describe('Stock symbols to show.'),
50 feed: z.enum(['iex', 'sip', 'delayed_sip']).default('iex').describe('Data feed.'),
51 }),
52 output: z.object({
53 symbols: z.array(z.string()),
54 count: z.number(),
55 rows: z.array(z.object({ symbol: z.string(), last: z.number().nullable(), change_pct: z.number().nullable() })),
56 }),
57 instructions:
58 'Latest Alpaca snapshots (last, bid, ask, change, change %, volume) for state.symbols, refreshed every 15 s. Set state.symbols and state.feed (iex free, sip paid).',
59 renders: [stockSnapshots],
60 summarize: (state, output) => `Alpaca watchlist: ${output.count ?? 0} of ${state.symbols?.length ?? 0} symbols`,
61 }),
62 account: defineView(AccountPanel, {
63 title: 'Alpaca account',
64 state: z.object({ live_account: z.boolean().default(false).describe('Show the LIVE account instead of paper.') }),
65 output: z.object({
66 mode: z.string(),
67 equity: z.number().nullable(),
68 cash: z.number().nullable(),
69 buying_power: z.number().nullable(),
70 day_pl: z.number().nullable(),
71 positions: z.number(),
72 }),
73 instructions:
74 'The Alpaca account summary and its positions, paper by default. Set state.live_account to true only when the user asks for the live account.',
75 renders: [account, positions],
76 summarize: (_state, output) => `Alpaca ${output.mode ?? 'paper'}: equity ${output.equity ?? '–'}, ${output.positions ?? 0} positions`,
77 }),
78 orders: defineView(Blotter, {
79 title: 'Alpaca orders',
80 state: z.object({
81 status: z.enum(['open', 'closed', 'all']).default('all'),
82 limit: z.number().int().min(1).max(500).default(50),
83 live_account: z.boolean().default(false).describe('Show the LIVE account instead of paper.'),
84 }),
85 output: z.object({ status: z.string(), count: z.number(), open: z.number() }),
86 instructions:
87 'An Alpaca order blotter, paper by default. Set state.status (open|closed|all) and state.limit. Its cancel buttons cancel only on the user\'s click and confirmation.',
88 renders: [orders],
89 summarize: (state, output) => `Alpaca orders (${state.status ?? 'all'}): ${output.count ?? 0}, ${output.open ?? 0} open`,
90 }),
91 },
92})