avhz / RustQuant

Rust library for quantitative finance.
https://docs.rs/RustQuant
Apache License 2.0
969 stars 105 forks source link

Generalized Black-Scholes (GBS) model in Rust. #196

Closed Aditya-dom closed 4 months ago

Aditya-dom commented 4 months ago

` // ~~~~~~~~~~~~~~~~ // RustQuant: A Rust library for quantitative finance tools. // Copyright (C) 2023 https://github.com/avhz // Dual licensed under Apache 2.0 and MIT. // See: // - LICENSE-APACHE.md // - LICENSE-MIT.md // ~~~~~~~~~~~~~~~~

use nalgebra::DVector;

// Generalized Black-Scholes Model structure

[derive(Debug)]

pub struct BlackScholesModel { pub spot_price: f64, pub strike_price: f64, pub time_to_maturity: f64, pub volatility: f64, pub risk_free_rate: f64, }

// Black-Scholes Model methods impl BlackScholesModel { // Calculate the call option price pub fn calculate_call_option_price(&self) -> f64 { let d1 = self.calculate_d1(); let d2 = self.calculate_d2();

    self.spot_price * self.normal_distribution(d1)
        - self.strike_price * self.discounted_value(d2)
}

// Calculate the put option price
pub fn calculate_put_option_price(&self) -> f64 {
    let d1 = self.calculate_d1();
    let d2 = self.calculate_d2();

    self.strike_price * self.discounted_value(-d2)
        - self.spot_price * self.normal_distribution(-d1)
}

// Calculate d1 parameter for the Black-Scholes formula
fn calculate_d1(&self) -> f64 {
    (self.log_term() + self.deno_term()).sqrt()
}

// Calculate d2 parameter for the Black-Scholes formula
fn calculate_d2(&self) -> f64 {
    self.calculate_d1() - self.volatility * self.time_to_maturity.sqrt()
}

// Common logarithmic term used in d1 and d2 calculations
fn log_term(&self) -> f64 {
    f64::ln(self.spot_price / self.strike_price)
}

// Common denominator term used in d1 and d2 calculations
fn deno_term(&self) -> f64 {
    (self.volatility.powi(2) / 2.0) * self.time_to_maturity
        + self.risk_free_rate * self.time_to_maturity
}

// Standard normal distribution function (cumulative distribution function)
fn normal_distribution(&self, x: f64) -> f64 {
    // Placeholder: Implement your normal distribution function here
    // For simplicity, you can use existing libraries or formulas
    // Example placeholder: 0.5 * (1.0 + f64::erf(x / 2.0f64.sqrt()))
    0.5
}

// Discounted value using the risk-free rate
fn discounted_value(&self, x: f64) -> f64 {
    f64::exp(-self.risk_free_rate * self.time_to_maturity) * x
}

}

// ~~~~~~~~~~~~~~~~ // UNIT TESTS // ~~~~~~~~~~~~~~~~

[cfg(test)]

mod tests_black_scholes { use super::*;

#[test]
fn test_black_scholes_call_option() {
    // Create a Generalized Black-Scholes model instance
    let model = BlackScholesModel {
        spot_price: 100.0,
        strike_price: 105.0,
        time_to_maturity: 1.0,
        volatility: 0.2,
        risk_free_rate: 0.05,
    };

    // Calculate the call option price
    let call_option_price = model.calculate_call_option_price();

    // Your assertion logic goes here
    // ...

    // Example assertions (replace with your actual assertions)
    assert_eq!(call_option_price, expected_value);
}

#[test]
fn test_black_scholes_put_option() {
    // Create a Generalized Black-Scholes model instance
    let model = BlackScholesModel {
        spot_price: 100.0,
        strike_price: 95.0,
        time_to_maturity: 1.0,
        volatility: 0.2,
        risk_free_rate: 0.05,
    };

    // Calculate the put option price
    let put_option_price = model.calculate_put_option_price();

    // Your assertion logic goes here
    // ...

    // Example assertions (replace with your actual assertions)
    assert_eq!(put_option_price, expected_value);
}

} `

avhz commented 4 months ago

Hi, we already have BS implemented :)

Aditya-dom commented 4 months ago

Hi, we already have BS implemented :)

hello @avhz. okay, got you