analysis.price_history
Retrieve historical OHLC price data for any market token with configurable time intervals from 1 hour to 1 month. Includes sparkline visualization to analyze price trends.
Instructions
Fetch historical OHLC price data for a market token over a configurable time window (1h to 1m). Returns price points with a sparkline visualization showing the price trend. Pro feature.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| token_id | Yes | Market token ID to fetch price history for | |
| interval | No | Time window: 1h, 6h, 1d, 1w, or 1m | 1d |
Implementation Reference
- src/index.ts:337-342 (registration)Registration of the 'analysis.price_history' tool with the MCP server using getPriceHistorySchema and handleGetPriceHistory.
server.tool( "analysis.price_history", "Fetch historical OHLC price data for a market token over a configurable time window (1h to 1m). Returns price points with a sparkline visualization showing the price trend. Pro feature.", getPriceHistorySchema.shape, safe("markets.price_history", async (input) => ({ content: [{ type: "text" as const, text: await handleGetPriceHistory(getPriceHistorySchema.parse(input)) }] })) ); - src/tools/get-price-history.ts:5-8 (schema)Input schema for the price history tool: takes token_id (string) and optional interval (1h, 6h, 1d, 1w, 1m) with default '1d'.
export const getPriceHistorySchema = z.object({ token_id: z.string().describe("Market token ID to fetch price history for"), interval: z.enum(["1h", "6h", "1d", "1w", "1m"]).optional().default("1d").describe("Time window: 1h, 6h, 1d, 1w, or 1m"), }); - src/tools/get-price-history.ts:10-53 (handler)Handler function that fetches price history, formats output with metrics table, recent prices, and a sparkline trend visualization.
export async function handleGetPriceHistory(input: z.infer<typeof getPriceHistorySchema>): Promise<string> { const isPro = await checkLicense(); if (!isPro) return requirePro("get_price_history"); const history = await getPriceHistory(input.token_id, input.interval as Interval); if (history.points.length === 0) { return `No price history available for this token (interval: ${input.interval}). The market may be too new or inactive.`; } const arrow = history.change >= 0 ? "+" : ""; let output = `## Price History (${input.interval})\n\n`; output += `| Metric | Value |\n|--------|-------|\n`; output += `| Open | $${history.open.toFixed(4)} |\n`; output += `| Close | $${history.close.toFixed(4)} |\n`; output += `| High | $${history.high.toFixed(4)} |\n`; output += `| Low | $${history.low.toFixed(4)} |\n`; output += `| Change | ${arrow}$${history.change.toFixed(4)} (${arrow}${history.changePct.toFixed(1)}%) |\n`; output += `| Data Points | ${history.points.length} |\n`; // Show recent price points (last 10) const recent = history.points.slice(-10); if (recent.length > 0) { output += `\n### Recent Prices\n\n`; output += `| Time | Price |\n|------|-------|\n`; for (const p of recent) { const time = p.timestamp.slice(11, 16); output += `| ${time} | $${p.price.toFixed(4)} |\n`; } } // Sparkline summary const sampled = samplePoints(history.points, 20); if (sampled.length >= 2) { const min = Math.min(...sampled.map((p) => p.price)); const max = Math.max(...sampled.map((p) => p.price)); const range = max - min || 1; const bars = sampled.map((p) => { const level = Math.round(((p.price - min) / range) * 7); return ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"][level]; }).join(""); output += `\n**Trend:** ${bars}\n`; } return output; } - src/tools/get-price-history.ts:55-59 (helper)Helper function samplePoints that downsamples price points for the sparkline display.
function samplePoints(points: { price: number }[], count: number): { price: number }[] { if (points.length <= count) return points; const step = (points.length - 1) / (count - 1); return Array.from({ length: count }, (_, i) => points[Math.round(i * step)]); } - src/services/price-history.ts:33-73 (helper)Core service function that fetches historical OHLC price data from the Polymarket CLOB API, computes high/low/open/close/change metrics.
export async function getPriceHistory( tokenId: string, interval: Interval = "1d", fidelity: number = 60 ): Promise<PriceHistory> { const startTs = Math.floor(Date.now() / 1000) - INTERVAL_SECONDS[interval]; const url = `${CLOB_API_BASE}/prices-history?market=${tokenId}&startTs=${startTs}&fidelity=${fidelity}`; log("info", `Fetching price history: ${tokenId} interval=${interval}`); try { const res = await fetchWithRetry(url, { retries: 1, timeoutMs: 8_000 }); if (!res.ok) { log("warn", `Price history API returned ${res.status} for ${tokenId}`); return emptyHistory(tokenId, interval); } const data = await res.json(); const history = data.history ?? []; if (history.length === 0) return emptyHistory(tokenId, interval); const points: PricePoint[] = history.map((h: any) => ({ timestamp: new Date(h.t * 1000).toISOString(), price: parseFloat(h.p), })); const prices = points.map((p) => p.price); const open = prices[0]; const close = prices[prices.length - 1]; const high = Math.max(...prices); const low = Math.min(...prices); const change = close - open; const changePct = open > 0 ? (change / open) * 100 : 0; return { tokenId, interval, points, high, low, open, close, change, changePct }; } catch (err) { log("error", `Failed to fetch price history for ${tokenId}: ${err}`); return emptyHistory(tokenId, interval); } }