|
15 | 15 | //! including the current price of the underlying asset, the strike price of the option, the time to expiration, the risk-free interest rate, |
16 | 16 | //! and the volatility of the underlying asset. |
17 | 17 | //! |
18 | | -//! ## Formula |
19 | | -//! |
20 | | -//! The price of an option using the Black-Scholes model is calculated as follows: |
21 | | -//! |
22 | | -//! ```text |
23 | | -//! C = S * N(d1) - X * e^(-rT) * N(d2) for a call option |
24 | | -//! P = X * e^(-rT) * N(-d2) - S * N(-d1) for a put option |
25 | | -//! ``` |
26 | | -//! |
27 | | -//! where: |
28 | | -//! - `C` is the price of the call option. |
29 | | -//! - `P` is the price of the put option. |
30 | | -//! - `S` is the current price of the underlying asset. |
31 | | -//! - `X` is the strike price of the option. |
32 | | -//! - `r` is the risk-free interest rate. |
33 | | -//! - `T` is the time to maturity. |
34 | | -//! - `N` is the cumulative distribution function of the standard normal distribution. |
35 | | -//! - `d1` and `d2` are calculated as follows: |
36 | | -//! ```text |
37 | | -//! d1 = (ln(S / X) + (r + 0.5 * σ^2) * T) / (σ * sqrt(T)) |
38 | | -//! d2 = d1 - σ * sqrt(T) |
39 | | -//! ``` |
40 | | -//! - `σ` is the volatility of the underlying asset. |
41 | | -//! |
42 | | -//! The payoff of the option is calculated as: |
43 | | -//! |
44 | | -//! ```text |
45 | | -//! payoff = max(ST - K, 0) for a call option |
46 | | -//! payoff = max(K - ST, 0) for a put option |
47 | | -//! ``` |
48 | | -//! |
49 | | -//! where: |
50 | | -//! - `ST` is the price of the underlying asset at maturity. |
51 | | -//! - `K` is the strike price of the option. |
52 | | -//! - `max` is the maximum function. |
53 | | -//! |
54 | 18 | //! ## References |
55 | 19 | //! |
56 | 20 | //! - [Wikipedia - Black-Scholes model](https://en.wikipedia.org/wiki/Black%E2%80%93Scholes_model) |
57 | 21 | //! - [Black-Scholes Calculator](https://www.math.drexel.edu/~pg/fin/VanillaCalculator.html) |
58 | 22 | //! - [Cash or Nothing Options' Greeks](https://quantpie.co.uk/bsm_bin_c_formula/bs_bin_c_summary.php) |
59 | 23 | //! - [Asset or Nothing Options' Greeks](https://quantpie.co.uk/bsm_bin_a_formula/bs_bin_a_summary.php) |
| 24 | +//! - Musiela, M., Rutkowski, M. Martingale Methods in Financial Modelling, 2nd Ed Springer, 2007 |
| 25 | +//! - Joshi, M. The Concepts and Practice of Mathematical Finance, 2nd Ed Cambridge University Press, 2008 |
60 | 26 | //! |
61 | 27 | //! ## Example |
62 | 28 | //! |
|
74 | 40 | use crate::options::{ |
75 | 41 | types::BinaryType::{AssetOrNothing, CashOrNothing}, |
76 | 42 | Instrument, Option, OptionGreeks, OptionPricing, OptionStrategy, OptionStyle, OptionType, |
77 | | - RainbowType, |
| 43 | + Permutation, RainbowType, |
78 | 44 | }; |
| 45 | +use rand_distr::num_traits::Pow; |
79 | 46 | use statrs::distribution::{Continuous, ContinuousCDF, Normal}; |
80 | 47 |
|
81 | 48 | /// A struct representing a Black-Scholes model. |
@@ -297,6 +264,57 @@ impl BlackScholesModel { |
297 | 264 | ) |
298 | 265 | } |
299 | 266 |
|
| 267 | + /// Calculate the price of a lookback option using the Black-Scholes formula. |
| 268 | + /// |
| 269 | + /// # Arguments |
| 270 | + /// |
| 271 | + /// * `option` - The option to price. |
| 272 | + /// * `normal` - The standard normal distribution. |
| 273 | + /// |
| 274 | + /// # Returns |
| 275 | + /// |
| 276 | + /// The price of the option. |
| 277 | + pub fn price_lookback<T: Option>(&self, option: &T, normal: &Normal) -> f64 { |
| 278 | + let max = option.instrument().max_spot(); |
| 279 | + let min = option.instrument().min_spot(); |
| 280 | + let sqrt_t = option.time_to_maturity().sqrt(); |
| 281 | + let s = option.instrument().spot(); |
| 282 | + let r = self.risk_free_rate; |
| 283 | + let t = option.time_to_maturity(); |
| 284 | + let vola = self.volatility; |
| 285 | + |
| 286 | + assert!(s > 0.0 && max > 0.0 && min > 0.0, "Spot prices must be > 0"); |
| 287 | + |
| 288 | + println!("max: {}, min: {}", max, min); |
| 289 | + |
| 290 | + let a1 = |s: f64, h: f64| ((s / h).ln() + (r + 0.5 * vola.powi(2)) * t) / (vola * sqrt_t); |
| 291 | + let a2 = |s: f64, h: f64| a1(s, h) - vola * sqrt_t; |
| 292 | + let a3 = |s: f64, h: f64| a1(s, h) - 2.0 * r * sqrt_t / vola; |
| 293 | + |
| 294 | + let phi = |x: f64| normal.cdf(x); |
| 295 | + |
| 296 | + match option.option_type() { |
| 297 | + OptionType::Call => { |
| 298 | + s * phi(a1(s, min)) |
| 299 | + - min * (-r * t).exp() * phi(a2(s, min)) |
| 300 | + - (0.5 * s * vola.powi(2)) / (r) |
| 301 | + * (phi(-a1(s, min)) |
| 302 | + - (-r * t).exp() |
| 303 | + * (min / s).pow((2f64 * r) / (vola.powi(2))) |
| 304 | + * phi(-a3(s, min))) |
| 305 | + } |
| 306 | + OptionType::Put => { |
| 307 | + -s * phi(-a1(s, max)) |
| 308 | + + max * (-r * t).exp() * phi(-a2(s, max)) |
| 309 | + + (0.5 * s * vola.powi(2)) / (r) |
| 310 | + * (phi(a1(s, max)) |
| 311 | + - (-r * t).exp() |
| 312 | + * (max / s).pow((2f64 * r) / (vola.powi(2))) |
| 313 | + * phi(a3(s, max))) |
| 314 | + } |
| 315 | + } |
| 316 | + } |
| 317 | + |
300 | 318 | /// Calculate the option price using the Black-Scholes formula with a given volatility. |
301 | 319 | /// |
302 | 320 | /// # Arguments |
@@ -369,6 +387,7 @@ impl OptionPricing for BlackScholesModel { |
369 | 387 | (_, OptionStyle::Binary(AssetOrNothing)) => self.price_asset_or_nothing(option, &normal), |
370 | 388 | (OptionType::Call, OptionStyle::Rainbow(_)) => self.price_rainbow_call(option, &normal), |
371 | 389 | (OptionType::Put, OptionStyle::Rainbow(_)) => self.price_rainbow_put(option, &normal), |
| 390 | + (_, OptionStyle::Lookback(Permutation::Floating)) => self.price_lookback(option, &normal), |
372 | 391 | _ => panic!("BlackScholesModel does not support this option type or style"), |
373 | 392 | } |
374 | 393 | } |
|
0 commit comments