spb/hfmarketdata
Public
Open high-frequency market data platform — FirstRate full-history downloader, DuckDB/Parquet lake, open REST API and React docs platform (www.hfmarketdata.io)
JavaScript 53.7%
Python 38.3%
CSS 4.6%
TypeScript 3.1%
1/**2 * Reusable analysis prompts. Each returns a single user message that tells the model which tools to3 * call and how to structure the answer.4 */5import { z } from 'zod';67export interface PromptDef<S extends Record<string, z.ZodTypeAny> = Record<string, z.ZodTypeAny>> {8 name: string;9 title: string;10 description: string;11 args: S;12 build: (args: z.infer<z.ZodObject<S>>) => string;13}1415function def<S extends Record<string, z.ZodTypeAny>>(p: PromptDef<S>): PromptDef<S> {16 return p;17}1819export const termStructureAnalysis = def({20 name: 'term-structure-analysis',21 title: 'Term structure analysis',22 description: 'Analyse the futures curve of a root (contango/backwardation, spreads, roll yield) on a date, optionally versus an earlier date.',23 args: {24 root: z.string().describe('Futures root, e.g. CL, NG, ES'),25 as_of: z.string().optional().describe('Curve date YYYY-MM-DD (default latest)'),26 compare_to: z.string().optional().describe('Earlier date to compare the curve with, YYYY-MM-DD'),27 },28 build: ({ root, as_of, compare_to }) => [29 `Analyse the ${root.toUpperCase()} futures term structure${as_of ? ` as of ${as_of}` : ' (latest available)'}${compare_to ? ` and compare it with ${compare_to}` : ''}.`,30 '',31 'Steps:',32 `1. Call get_term_structure(root="${root.toUpperCase()}"${as_of ? `, as_of="${as_of}"` : ''}).${compare_to ? ` Then call it again with as_of="${compare_to}".` : ''}`,33 '2. Determine whether the curve is in contango (upward sloping) or backwardation (downward sloping); quantify the front-to-second spread in price and in % annualised (spread / front price × 365 / days between expiries).',34 '3. Note any kinks (seasonality for NG/ZC, delivery-month effects for CL) and where volume/open interest concentrate.',35 '4. Explain the implied roll yield for a long front-month position and what the shape suggests about inventories / financing.',36 '5. If the API reports missing prices, say so explicitly — never fill gaps.',37 '',38 'Output: a short table (contract · expiry · price · spread vs front · OI) followed by 4-6 bullet conclusions.',39 ].join('\n'),40});4142export const compareContracts = def({43 name: 'compare-contracts',44 title: 'Compare two futures contracts',45 description: 'Compare two individual futures contracts (e.g. ESZ25 vs ESH26) over a window: performance, spread, volume/OI migration, calendar-spread behaviour.',46 args: {47 symbol_a: z.string().describe('First contract symbol, e.g. ESZ25'),48 symbol_b: z.string().describe('Second contract symbol, e.g. ESH26'),49 days: z.string().optional().describe('Look-back window in calendar days (default 30)'),50 },51 build: ({ symbol_a, symbol_b, days }) => {52 const n = Number(days) > 0 ? Number(days) : 30;53 const a = symbol_a.toUpperCase();54 const b = symbol_b.toUpperCase();55 return [56 `Compare the futures contracts ${a} and ${b} over the last ${n} days.`,57 '',58 'Steps:',59 `1. Call get_coverage(kind="futures_contract", symbol="${a}") and the same for ${b} to know the available range and any gaps.`,60 `2. Call get_bars(asset="futures_contract", symbol="${a}", timeframe="1day", start=<today - ${n} days>) and the same for ${b}.`,61 '3. Align both series on datetime and compute: total return, annualised volatility, the daily calendar spread (B − A) and its trend, and the share of volume/open interest in each contract (roll migration).',62 '4. Flag whichever contract looks like the front month and estimate the likely roll window from the volume crossover.',63 '5. Mention explicitly if a day is missing in one leg — do not interpolate.',64 '',65 'Output: a compact comparison table then 3-5 bullets of interpretation. Ask before pulling intraday data (large).',66 ].join('\n');67 },68});6970export const fundamentalsSnapshot = def({71 name: 'fundamentals-snapshot',72 title: 'Fundamentals snapshot',73 description: 'One-page fundamental picture of a US company: latest ratios, last quarters, filings calendar and the caveats of point-in-time data.',74 args: {75 ticker: z.string().describe('US ticker, e.g. AAPL'),76 quarters: z.string().optional().describe('Number of recent quarters to show (default 4)'),77 },78 build: ({ ticker, quarters }) => {79 const q = Number(quarters) > 0 ? Number(quarters) : 4;80 const t = ticker.toUpperCase();81 return [82 `Build a fundamentals snapshot of ${t}.`,83 '',84 'Steps:',85 `1. get_ratios(ticker="${t}") for the current valuation / profitability / leverage picture.`,86 `2. get_financial_statements(ticker="${t}", statement="income", period="quarterly", limit=${q}) and the same for "cashflow" (revenue, operating income, net income, operating cash flow, capex → free cash flow).`,87 `3. get_filings(ticker="${t}", forms=["10-K","10-Q","8-K"], limit=8) to date the numbers and spot recent events.`,88 `4. Optionally get_ratios_daily(ticker="${t}", metrics=["pe","fcf_yield"], start=<1 year ago>) to place today's valuation in its 1-year range.`,89 '5. Every figure must cite the period end and the filing date it comes from (point-in-time). Say when a metric is unavailable rather than estimating it.',90 '',91 'Output: headline (price-agnostic) summary, a quarterly table, valuation context, 3 risks/observations drawn only from the data returned.',92 ].join('\n');93 },94});9596export const PROMPTS: PromptDef<any>[] = [termStructureAnalysis, compareContracts, fundamentalsSnapshot];97