blackscholes_wasm/implied_volatility.rs
1use crate::{constants::*, Inputs};
2use wasm_bindgen::prelude::*;
3
4#[wasm_bindgen]
5impl Inputs {
6 /// Calculates the implied volatility of the option.
7 /// Tolerance is the max error allowed for the implied volatility,
8 /// the lower the tolerance the more iterations will be required.
9 /// Recommended to be a value between 0.001 - 0.0001 for highest efficiency/accuracy.
10 /// Initializes estimation of sigma using Brenn and Subrahmanyam (1998) method of calculating initial iv estimation.
11 /// Uses Newton Raphson algorithm to calculate implied volatility.
12 /// # Requires
13 /// s, k, r, q, t, p
14 /// # Returns
15 /// f32 of the implied volatility of the option.
16 /// # Example:
17 /// ```
18 /// use blackscholes::{Inputs, OptionType};
19 /// let inputs = Inputs::new(OptionType::Call, 100.0, 100.0, Some(0.2), 0.05, 0.2, 20.0/365.25, None);
20 /// let iv = inputs.calc_iv(0.0001).unwrap();
21 /// ```
22 pub fn calc_iv(&self, tolerance: f32) -> Result<f32, String> {
23 let mut inputs: Inputs = self.clone();
24
25 let p = self
26 .p
27 .ok_or("inputs.p must contain Some(f32), found None".to_string())?;
28 // Initialize estimation of sigma using Brenn and Subrahmanyam (1998) method of calculating initial iv estimation.
29 let mut sigma: f32 = (2.0 * PI / inputs.t).sqrt() * (p / inputs.s);
30 // Initialize diff to 100 for use in while loop
31 let mut diff: f32 = 100.0;
32
33 // Uses Newton Raphson algorithm to calculate implied volatility.
34 // Test if the difference between calculated option price and actual option price is > tolerance,
35 // if so then iterate until the difference is less than tolerance
36 while diff.abs() > tolerance {
37 inputs.sigma = Some(sigma);
38 diff = Inputs::calc_price(&inputs)? - p;
39 sigma -= diff / (Inputs::calc_vega(&inputs)? * 100.0);
40 }
41 Ok(sigma)
42 }
43}