Skip to main content
Glama
Ademscodeisnotsobad

Quant Companion MCP

simulatePrice.ts5.15 kB
/** * MCP Tool: simulate_price * * Simulate future price paths and analyze probability distributions. */ import { z } from "zod"; import { simulateTerminalPrices, mean, stdDev, percentiles } from "@quant-companion/core"; import { LIMITS } from "../errors"; export const simulatePriceSchema = z.object({ spot: z.number().positive().describe("Current spot price"), rate: z .number() .describe("Risk-free rate (annualized, e.g., 0.05 for 5%)"), vol: z .number() .positive() .describe("Volatility (annualized, e.g., 0.25 for 25%)"), timeHorizonYears: z .number() .positive() .describe("Time horizon in years (e.g., 0.5 for 6 months)"), dividendYield: z .number() .optional() .default(0) .describe("Dividend yield (annualized, default 0)"), paths: z .number() .int() .positive() .max(LIMITS.MAX_PATHS) .default(LIMITS.DEFAULT_PATHS) .describe(`Number of simulation paths (default ${LIMITS.DEFAULT_PATHS}, max ${LIMITS.MAX_PATHS})`), targetPrice: z .number() .positive() .optional() .describe("Optional target price to calculate probability of reaching"), }); export type SimulatePriceInput = z.infer<typeof simulatePriceSchema>; export interface PriceDistribution { mean: number; median: number; stdDev: number; percentile5: number; percentile25: number; percentile75: number; percentile95: number; min: number; max: number; } export interface TargetAnalysis { targetPrice: number; targetReturnPercent: number; probabilityAbove: number; probabilityBelow: number; } export interface SimulatePriceOutput { spot: number; timeHorizonYears: number; paths: number; distribution: PriceDistribution; expectedReturn: number; expectedReturnPercent: number; targetAnalysis?: TargetAnalysis; } export function simulatePrice(input: SimulatePriceInput): SimulatePriceOutput { // Enforce limits with specific error for LIMIT_EXCEEDED if (input.paths > LIMITS.MAX_PATHS) { const err = new Error(`Limit exceeded: paths must be <= ${LIMITS.MAX_PATHS}`); err.name = "LIMIT_EXCEEDED"; throw err; } const terminalPrices = simulateTerminalPrices({ spot: input.spot, rate: input.rate, vol: input.vol, timeToMaturity: input.timeHorizonYears, dividendYield: input.dividendYield, paths: input.paths, }); // Compute percentiles efficiently const pctls = percentiles(terminalPrices, [0.05, 0.25, 0.5, 0.75, 0.95]); // Compute stats const sorted = [...terminalPrices].sort((a, b) => a - b); const n = sorted.length; const avgPrice = mean(terminalPrices); const distribution: PriceDistribution = { mean: avgPrice, median: pctls[0.5], stdDev: stdDev(terminalPrices), percentile5: pctls[0.05], percentile25: pctls[0.25], percentile75: pctls[0.75], percentile95: pctls[0.95], min: sorted[0], max: sorted[n - 1], }; const expectedReturn = avgPrice - input.spot; const expectedReturnPercent = (expectedReturn / input.spot) * 100; const result: SimulatePriceOutput = { spot: input.spot, timeHorizonYears: input.timeHorizonYears, paths: input.paths, distribution, expectedReturn, expectedReturnPercent, }; // Target analysis if specified if (input.targetPrice !== undefined) { const aboveTarget = terminalPrices.filter((p) => p >= input.targetPrice!).length; const probabilityAbove = aboveTarget / n; result.targetAnalysis = { targetPrice: input.targetPrice, targetReturnPercent: ((input.targetPrice - input.spot) / input.spot) * 100, probabilityAbove, probabilityBelow: 1 - probabilityAbove, }; } return result; } export const simulatePriceDefinition = { name: "simulate_price", description: `Simulate future price paths using Geometric Brownian Motion and analyze the probability distribution of terminal prices. Optionally calculate the probability of reaching a target price. Use this to answer questions like 'What's the probability NVDA ends 20% higher in 6 months?' Max ${LIMITS.MAX_PATHS} paths.`, inputSchema: { type: "object", properties: { spot: { type: "number", description: "Current spot price", }, rate: { type: "number", description: "Risk-free rate (annualized decimal, e.g., 0.05 for 5%)", }, vol: { type: "number", description: "Volatility (annualized decimal, e.g., 0.25 for 25%)", }, timeHorizonYears: { type: "number", description: "Time horizon in years (e.g., 0.5 for 6 months)", }, dividendYield: { type: "number", description: "Dividend yield (annualized decimal, default 0)", }, paths: { type: "number", description: `Number of simulation paths (default ${LIMITS.DEFAULT_PATHS}, max ${LIMITS.MAX_PATHS})`, }, targetPrice: { type: "number", description: "Optional target price to calculate probability of reaching", }, }, required: ["spot", "rate", "vol", "timeHorizonYears"], }, };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Ademscodeisnotsobad/Quant-Companion-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server