quant-opts 0.1.0

High-performance Rust library for option pricing and risk
Documentation
use crate::{
    OptionType,
    core::{MarketData, VanillaOption},
    lets_be_rational::normal_distribution::{standard_normal_cdf, standard_normal_pdf},
};

pub(super) fn d1_d2(
    option: &VanillaOption,
    market: &MarketData,
    sigma: f64,
) -> Result<(f64, f64), String> {
    if !sigma.is_finite() {
        return Err("Volatility must be finite".to_string());
    }

    let s = market.spot;
    let k = option.strike;
    let r = market.rate;
    let q = market.dividend_yield;
    let t = option.maturity;

    let part1 = (s / k).ln();
    if part1.is_infinite() {
        return Err("Log from s/k is infinity".to_string());
    }

    if t == 0.0 {
        return Err("Time to maturity is 0".to_string());
    }

    let part2 = (r - q + sigma.powi(2) / 2.0) * t;
    let num_d1 = part1 + part2;
    let den = sigma * t.sqrt();

    let d1 = num_d1 / den;
    let d2 = d1 - den;

    Ok((d1, d2))
}

pub(super) fn nd1_nd2(
    option: &VanillaOption,
    market: &MarketData,
    sigma: f64,
) -> Result<(f64, f64), String> {
    let (d1, d2) = d1_d2(option, market, sigma)?;

    let (nd1, nd2) = match option.kind {
        OptionType::Call => (standard_normal_cdf(d1), standard_normal_cdf(d2)),
        OptionType::Put => (standard_normal_cdf(-d1), standard_normal_cdf(-d2)),
    };

    Ok((nd1, nd2))
}

pub(super) fn nprimed1(
    option: &VanillaOption,
    market: &MarketData,
    sigma: f64,
) -> Result<f64, String> {
    let (d1, _) = d1_d2(option, market, sigma)?;
    Ok(standard_normal_pdf(d1))
}