/**
* MCP Tool: compute_implied_vol
*
* Recover implied volatility from observed option price.
*/
import { z } from "zod";
import { impliedVol, BlackScholesParams } from "@quant-companion/core";
export const computeImpliedVolSchema = z.object({
observedPrice: z.number().nonnegative().describe("Observed market price of the option"),
spot: z.number().positive().describe("Current spot price of the underlying"),
strike: z.number().positive().describe("Strike price of the option"),
rate: z
.number()
.describe("Risk-free interest rate (annualized, e.g., 0.05 for 5%)"),
timeToMaturity: z
.number()
.positive()
.describe("Time to maturity in years (e.g., 0.5 for 6 months)"),
dividendYield: z
.number()
.optional()
.default(0)
.describe("Dividend yield (annualized, default 0)"),
optionType: z.enum(["call", "put"]).describe("Option type: 'call' or 'put'"),
});
export type ComputeImpliedVolInput = z.infer<typeof computeImpliedVolSchema>;
export interface ComputeImpliedVolOutput {
impliedVol: number;
impliedVolPercent: number;
}
export function computeImpliedVol(
input: ComputeImpliedVolInput
): ComputeImpliedVolOutput {
const params: Omit<BlackScholesParams, "vol"> = {
spot: input.spot,
strike: input.strike,
rate: input.rate,
timeToMaturity: input.timeToMaturity,
dividendYield: input.dividendYield,
optionType: input.optionType,
};
const iv = impliedVol(input.observedPrice, params);
return {
impliedVol: iv,
impliedVolPercent: iv * 100,
};
}
export const computeImpliedVolDefinition = {
name: "compute_implied_vol",
description:
"Recover the implied volatility from an observed option price using Newton-Raphson with bisection fallback. Use this to analyze if options are expensive or cheap relative to historical volatility.",
inputSchema: {
type: "object",
properties: {
observedPrice: {
type: "number",
description: "The observed market price of the option",
},
spot: {
type: "number",
description: "Current spot price of the underlying asset",
},
strike: {
type: "number",
description: "Strike price of the option",
},
rate: {
type: "number",
description:
"Risk-free interest rate (annualized decimal, e.g., 0.05 for 5%)",
},
timeToMaturity: {
type: "number",
description: "Time to expiration in years (e.g., 0.25 for 3 months)",
},
dividendYield: {
type: "number",
description: "Dividend yield (annualized decimal, default 0)",
},
optionType: {
type: "string",
enum: ["call", "put"],
description: "Option type: 'call' or 'put'",
},
},
required: [
"observedPrice",
"spot",
"strike",
"rate",
"timeToMaturity",
"optionType",
],
},
};