Skip to content

Commit

Permalink
feat: BarrierOption Payoff and Monte-Carlo
Browse files Browse the repository at this point in the history
  • Loading branch information
avhz authored and avhz committed Aug 10, 2024
1 parent 9c6fa43 commit f8b8253
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 95 deletions.
72 changes: 25 additions & 47 deletions src/instruments/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,65 +9,43 @@

//! Financial instrument types and modules (bonds, options, etc).
//!
//! ### Bonds
//! ### Options
//!
//! - Prices:
//! - [x] The Vasicek Model
//! - [x] The Cox, Ingersoll, and Ross Model
//! - [x] The Hull–White (One-Factor) Model
//! - [ ] The Rendleman and Bartter Model
//! - [ ] The Ho–Lee Model
//! - [ ] The Black–Derman–Toy Model
//! - [ ] The Black–Karasinski Model
//! - [ ] Duration
//! - [ ] Convexity
//! The following options and pricing methods are implemented:
//!
//! ### Options
//! | Option | Analytic | Monte-Carlo | Finite Difference | Lattice | Greeks |
//! |--------|:--------:|:-----------:|:-----------------:|:-------:|:------:|
//! | Asian |❌|✅|❌|❌|❌|
//! | Barrier |❌|✅|❌|❌|❌|
//! | Basket |❌|❌|❌|❌|❌|
//! | Binary |❌|✅|❌|❌|❌|
//! | Chooser |❌|❌|❌|❌|❌|
//! | Cliquet |❌|❌|❌|❌|❌|
//! | Compound |❌|❌|❌|❌|❌|
//! | Exchange |❌|❌|❌|❌|❌|
//! | Forward Start |❌|❌|❌|❌|❌|
//! | Lookback |❌|❌|❌|❌|❌|
//! | Power |❌|✅|❌|❌|❌|
//! | Quanto |❌|❌|❌|❌|❌|
//! | Spread |❌|❌|❌|❌|❌|
//! | Supershare |❌|✅|❌|❌|❌|
//! | Vanilla |✅|✅|✅|✅|✅|
//!
//! - Closed-form price solutions:
//! - [x] Heston Model
//! - [x] Barrier
//! - [x] European
//! - [x] Greeks/Sensitivities
//! - [x] Lookback
//! - [x] Asian: Continuous Geometric Average
//! - [x] Forward Start
//! - [x] Bachelier and Modified Bachelier
//! - [x] Generalised Black-Scholes-Merton
//! - [ ] Basket
//! - [ ] Rainbow
//! - [ ] American
//! - [x] Bachelier and Modified Bachelier
//! - [x] Heston Model
//!
//! - Lattice models:
//! - [x] Binomial Tree (Cox-Ross-Rubinstein)
//!
//! The stochastic process generators can be used to price path-dependent options via Monte-Carlo.
//!
//! - Monte Carlo pricing:
//! - [x] Lookback
//! - [ ] Asian
//! - [ ] Chooser
//! - [ ] Barrier
//!
//! ```ignore
//! use RustQuant::instruments::*;
//! use time::{Duration, OffsetDateTime};
//! ### Bonds
//!
//! let VanillaOption = EuropeanOption {
//! initial_price: 100.,
//! strike_price: 110.,
//! risk_free_rate: 0.05,
//! volatility: 0.3,
//! dividend_rate: 0.02,
//! evaluation_date: None,
//! expiration_date: OffsetDateTime::now_utc() + Duration::days(365),
//! };
//! ### FX
//!
//! let prices = VanillaOption.price();
//! ### Equities
//!
//! println!("Call price = {}", prices.0);
//! println!("Put price = {}", prices.1);
//! ```
//! ### Commodities

/// Base trait for all instruments.
pub mod instrument;
Expand Down
28 changes: 25 additions & 3 deletions src/instruments/options/asian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@
// - LICENSE-MIT.md
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

use derive_builder::Builder;

use super::option_flags::*;
use super::{AveragingMethod, OptionContract};
use crate::instruments::Payoff;

/// Asian option.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Builder)]
pub struct AsianOption {
/// The option contract.
pub contract: OptionContract,
Expand All @@ -21,6 +27,21 @@ pub struct AsianOption {
pub strike: Option<f64>,
}

impl AsianOption {
/// Create a new Asian option.
pub fn new(
contract: OptionContract,
averaging_method: AveragingMethod,
strike: Option<f64>,
) -> Self {
Self {
contract,
averaging_method,
strike,
}
}
}

impl Payoff for AsianOption {
type Underlying = Vec<f64>;

Expand All @@ -38,14 +59,15 @@ impl Payoff for AsianOption {
};

match self.contract.strike_flag {
StrikeFlag::Fixed => match self.contract.type_flag {
Some(StrikeFlag::Fixed) => match self.contract.type_flag {
TypeFlag::Call => (average - self.strike.unwrap_or_default()).max(0.0),
TypeFlag::Put => (self.strike.unwrap_or_default() - average).max(0.0),
},
StrikeFlag::Floating => match self.contract.type_flag {
Some(StrikeFlag::Floating) => match self.contract.type_flag {
TypeFlag::Call => (terminal - average).max(0.0),
TypeFlag::Put => (average - terminal).max(0.0),
},
None => panic!("Strike flag not set."),
}
}
}
66 changes: 66 additions & 0 deletions src/instruments/options/barrier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
// - LICENSE-MIT.md
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

use crate::instruments::Payoff;

use super::{BarrierType, OptionContract, TypeFlag};

/// Barrier option.
#[derive(Debug, Clone)]
pub struct BarrierOption {
Expand All @@ -25,3 +29,65 @@ pub struct BarrierOption {
/// Rebate amount.
pub rebate: Option<f64>,
}

impl Payoff for BarrierOption {
type Underlying = Vec<f64>;

fn payoff(&self, underlying: Self::Underlying) -> f64 {
let s = underlying;
let b = self.barrier;
let k = self.strike;

let terminal = s.last().unwrap();

let above = s.iter().any(|&x| x >= b);
let below = s.iter().any(|&x| x <= b);

match self.contract.type_flag {
TypeFlag::Call => {
let payoff = (terminal - k).max(0.0);

match self.barrier_type {
BarrierType::UpAndOut => match above {
true => 0.0,
false => payoff,
},
BarrierType::DownAndOut => match below {
true => 0.0,
false => payoff,
},
BarrierType::UpAndIn => match above {
true => payoff,
false => 0.0,
},
BarrierType::DownAndIn => match below {
true => payoff,
false => 0.0,
},
}
}
TypeFlag::Put => {
let payoff = (k - terminal).max(0.0);

match self.barrier_type {
BarrierType::UpAndOut => match above {
true => 0.0,
false => payoff,
},
BarrierType::DownAndOut => match below {
true => 0.0,
false => payoff,
},
BarrierType::UpAndIn => match above {
true => payoff,
false => 0.0,
},
BarrierType::DownAndIn => match below {
true => payoff,
false => 0.0,
},
}
}
}
}
}
4 changes: 4 additions & 0 deletions src/instruments/options/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
// - LICENSE-MIT.md
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

use crate::instruments::Payoff;

use super::{BinaryType, OptionContract, TypeFlag};

/// Binary option.
#[derive(Debug, Clone)]
pub struct BinaryOption {
Expand Down
28 changes: 18 additions & 10 deletions src/instruments/options/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,20 @@ pub use crate::instruments::options::{
black_scholes_merton::*, implied_volatility::*, merton_jump_diffusion::*, option_contract::*,
};

// /// Asian option pricers.
// pub mod asian;
/// Asian option pricers.
pub mod asian;
pub use asian::*;

// /// Bachelier option pricer.
// pub mod bachelier;

// /// Barrier option pricers.
// pub mod barrier;
/// Barrier option pricers.
pub mod barrier;
pub use barrier::*;

// /// Binary option pricers.
// pub mod binary;
/// Binary option pricers.
pub mod binary;
pub use binary::*;

// /// Binomial option pricers.
// pub mod binomial;
Expand All @@ -46,10 +49,11 @@ pub mod merton_jump_diffusion;

/// Base option traits.
pub mod option_contract;
// pub use option_contract::*;
pub use option_contract::*;

// /// Power option pricers.
// pub mod power;
/// Power options.
pub mod power;
pub use power::*;

/// Finite Difference Pricer
pub mod finite_difference_pricer;
Expand All @@ -58,6 +62,10 @@ pub mod finite_difference_pricer;
pub mod option_flags;
pub use option_flags::*;

/// Vanilla option pricers.
/// Vanilla option.
pub mod vanilla;
pub use vanilla::*;

/// Supershare options.
pub mod supershare;
pub use supershare::*;
11 changes: 7 additions & 4 deletions src/instruments/options/power.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@
// - LICENSE-MIT.md
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

use super::{OptionContract, TypeFlag};
use crate::instruments::Payoff;

/// Power Option.
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone)]
pub struct PowerOption {
/// The option contract.
pub contract: OptionContract,

/// Strike price of the option.
pub strike_price: f64,
pub strike: f64,

/// Power parameter.
pub power: f64,
Expand All @@ -24,7 +27,7 @@ pub struct PowerOption {
#[derive(Debug, Clone, Copy)]
pub struct PowerContract {
/// Strike price of the option.
pub strike_price: f64,
pub strike: f64,

/// Power parameter.
pub power: f64,
Expand All @@ -34,7 +37,7 @@ impl Payoff for PowerContract {
type Underlying = f64;

fn payoff(&self, underlying: Self::Underlying) -> f64 {
(underlying / self.strike_price).powf(self.power)
(underlying / self.strike).powf(self.power)
}
}

Expand Down
7 changes: 5 additions & 2 deletions src/instruments/options/supershare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
// - LICENSE-MIT.md
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

use super::OptionContract;
use crate::instruments::Payoff;

/// Supershare option.
#[derive(Debug, Clone)]
pub struct SupershareOption {
Expand All @@ -24,8 +27,8 @@ impl Payoff for SupershareOption {
type Underlying = f64;

fn payoff(&self, underlying: Self::Underlying) -> f64 {
match (strike_1..=strike_2).contains(&underlying) {
true => underlying / strike_1,
match (self.strike_1..=self.strike_2).contains(&underlying) {
true => underlying / self.strike_1,
false => 0.0,
}
}
Expand Down
Loading

0 comments on commit f8b8253

Please sign in to comment.