/**
* Tests for implied volatility solver
*/
import { describe, it, expect } from "vitest";
import { impliedVol } from "./impliedVol";
import { priceBlackScholes } from "./blackScholes";
describe("impliedVol", () => {
it("recovers known volatility", () => {
const params = {
spot: 100,
strike: 100,
rate: 0.05,
timeToMaturity: 1,
optionType: "call" as const,
};
const knownVol = 0.25;
const price = priceBlackScholes({ ...params, vol: knownVol }).price;
const recoveredVol = impliedVol(price, params);
expect(recoveredVol).toBeCloseTo(knownVol, 4);
});
it("works for OTM options", () => {
const params = {
spot: 100,
strike: 120,
rate: 0.05,
timeToMaturity: 0.5,
optionType: "call" as const,
};
const knownVol = 0.3;
const price = priceBlackScholes({ ...params, vol: knownVol }).price;
const recoveredVol = impliedVol(price, params);
expect(recoveredVol).toBeCloseTo(knownVol, 4);
});
it("works for ITM puts", () => {
const params = {
spot: 100,
strike: 110,
rate: 0.05,
timeToMaturity: 0.25,
optionType: "put" as const,
};
const knownVol = 0.35;
const price = priceBlackScholes({ ...params, vol: knownVol }).price;
const recoveredVol = impliedVol(price, params);
expect(recoveredVol).toBeCloseTo(knownVol, 4);
});
it("handles extreme volatilities", () => {
const params = {
spot: 100,
strike: 100,
rate: 0.05,
timeToMaturity: 1,
optionType: "call" as const,
};
// High vol
const highVol = 1.5;
const highPrice = priceBlackScholes({ ...params, vol: highVol }).price;
const recoveredHighVol = impliedVol(highPrice, params);
expect(recoveredHighVol).toBeCloseTo(highVol, 3);
// Low vol
const lowVol = 0.05;
const lowPrice = priceBlackScholes({ ...params, vol: lowVol }).price;
const recoveredLowVol = impliedVol(lowPrice, params);
expect(recoveredLowVol).toBeCloseTo(lowVol, 3);
});
it("throws for invalid prices", () => {
const params = {
spot: 100,
strike: 100,
rate: 0.05,
timeToMaturity: 0.5,
optionType: "call" as const,
};
// Price below intrinsic value
expect(() => impliedVol(0.001, params)).toThrow();
});
it("handles dividend yield", () => {
const params = {
spot: 100,
strike: 100,
rate: 0.05,
timeToMaturity: 1,
dividendYield: 0.02,
optionType: "call" as const,
};
const knownVol = 0.25;
const price = priceBlackScholes({ ...params, vol: knownVol }).price;
const recoveredVol = impliedVol(price, params);
expect(recoveredVol).toBeCloseTo(knownVol, 4);
});
});