Skip to content

Commit bc9f706

Browse files
committed
add blacksholes
1 parent ed7a42e commit bc9f706

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
* [Word Break](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/word_break.rs)
106106
* Financial
107107
* [Present Value](https://github.com/TheAlgorithms/Rust/blob/master/src/financial/present_value.rs)
108+
* [Black Scholes](https://github.com/TheAlgorithms/Rust/blob/master/src/financial/black_scholes.rs)
108109
* General
109110
* [Convex Hull](https://github.com/TheAlgorithms/Rust/blob/master/src/general/convex_hull.rs)
110111
* [Fisher Yates Shuffle](https://github.com/TheAlgorithms/Rust/blob/master/src/general/fisher_yates_shuffle.rs)

src/financial/black_scholes.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/// implementation of the Black-Scholes model for option pricing
2+
/// The model essentially calculates the probability-weighted present value of the option's potential payoffs.
3+
/// The N(d₁) and N(d₂) terms represent probabilities related to the option finishing in-the-money (intrinsic value of the option).
4+
use std::f64::consts::PI;
5+
6+
#[derive(PartialEq, Eq, Debug)]
7+
pub enum BlackScholesError {
8+
InvalidParameters,
9+
}
10+
11+
// accumulate standard normal distribution function
12+
fn normal_cdf(x: f64) -> f64 {
13+
0.5 * (1.0 + (x / (2.0_f64.sqrt() * PI)).exp().tanh())
14+
}
15+
16+
// Round to 4 decimal
17+
fn round_to_precision(value: f64, precision: u32) -> f64 {
18+
let multiplier = 10.0f64.powi(precision as i32);
19+
(value * multiplier).round() / multiplier
20+
}
21+
22+
pub fn black_scholes(
23+
spot_price: f64, // current price of the stock
24+
strike_price: f64, // price you can buy the stock at
25+
time_to_maturity: f64, // time until the option expires (in years)
26+
risk_free_rate: f64, // risk free interest rate (annualized)
27+
volatility: f64,
28+
) -> Result<f64, BlackScholesError> {
29+
if spot_price <= 0.0
30+
|| strike_price <= 0.0
31+
|| time_to_maturity < 0.0
32+
|| risk_free_rate < 0.0
33+
|| volatility < 0.0
34+
{
35+
return Err(BlackScholesError::InvalidParameters);
36+
}
37+
38+
let d1 = (spot_price.ln() - strike_price.ln()
39+
+ (risk_free_rate + 0.5 * volatility.powi(2)) * time_to_maturity)
40+
/ (volatility * time_to_maturity.sqrt());
41+
let d2 = d1 - volatility * time_to_maturity.sqrt();
42+
43+
let n_d1 = normal_cdf(d1);
44+
let n_d2 = normal_cdf(d2);
45+
46+
let call_option_price =
47+
spot_price * n_d1 - strike_price * (-risk_free_rate * time_to_maturity).exp() * n_d2;
48+
49+
Ok(round_to_precision(call_option_price, 4))
50+
}
51+
52+
#[cfg(test)]
53+
mod tests {
54+
use super::*;
55+
macro_rules! test_black_scholes {
56+
($($name:ident: $inputs:expr,)*) => {
57+
$(
58+
#[test]
59+
fn $name() {
60+
let (spot_price, strike_price, time_to_maturity, risk_free_rate, volatility) = $inputs;
61+
let expected = black_scholes(spot_price, strike_price, time_to_maturity, risk_free_rate, volatility).unwrap();
62+
assert!(expected >= 0.0);
63+
}
64+
)*
65+
}
66+
}
67+
68+
macro_rules! test_black_scholes_Err {
69+
($($name:ident: $inputs:expr,)*) => {
70+
$(
71+
#[test]
72+
fn $name() {
73+
let (spot_price, strike_price, time_to_maturity, risk_free_rate, volatility) = $inputs;
74+
assert_eq!(black_scholes(spot_price, strike_price, time_to_maturity, risk_free_rate, volatility).unwrap_err(), BlackScholesError::InvalidParameters);
75+
}
76+
)*
77+
}
78+
}
79+
80+
test_black_scholes! {
81+
valid_parameters: (100.0, 100.0, 1.0, 0.05, 0.2),
82+
another_valid_case: (150.0, 100.0, 2.0, 0.03, 0.25),
83+
}
84+
85+
test_black_scholes_Err! {
86+
negative_spot_price: (-100.0, 100.0, 1.0, 0.05, 0.2),
87+
zero_strike_price: (100.0, 0.0, 1.0, 0.05, 0.2),
88+
negative_time_to_maturity: (100.0, 100.0, -1.0, 0.05, 0.2),
89+
negative_risk_free_rate: (100.0, 100.0, 1.0, -0.05, 0.2),
90+
negative_volatility: (100.0, 100.0, 1.0, 0.05, -0.2),
91+
}
92+
}

src/financial/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
mod black_scholes;
12
mod present_value;
3+
4+
pub use self::black_scholes::black_scholes;
25
pub use present_value::present_value;

0 commit comments

Comments
 (0)