Skip to content

Commit

Permalink
Epsilon value for numerical differentiation
Browse files Browse the repository at this point in the history
  • Loading branch information
Liberxue committed Aug 12, 2024
1 parent 7ca0e44 commit 8d17a79
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 53 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,5 +196,5 @@ fn test_dance() {

# Contributing

Contributions are welcome! [Please open an issue](https://github.com/Liberxue/cqf/issues/new) or [submit PR ] (https://github.com/Liberxue/cqf/pulls) for any improvements or new features.
Contributions are welcome! [Please open an issue](https://github.com/Liberxue/cqf/issues/new) or [submit PR ](https://github.com/Liberxue/cqf/pulls) for any improvements or new features.

Binary file added cli/options_price_chart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 0 additions & 10 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,2 @@
//pub mod models {
// pub mod black_scholes;
// pub mod monte_carlo;
//}
//
//pub mod strategies {
// pub mod butterfly;
// pub mod collar;
//}

pub mod models;
pub mod strategies;
41 changes: 21 additions & 20 deletions core/src/models/binomial_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use crate::models::{OptionParameters, OptionPricingModel};
pub struct BinomialTreeModel {
/// Number of steps in the binomial tree model.
pub steps: usize,
/// Epsilon value for numerical differentiation.
pub epsilon: f64,
}

enum OptionType {
Expand All @@ -13,13 +15,14 @@ enum OptionType {
}

impl BinomialTreeModel {
/// Creates a new `BinomialTreeModel` with a specified number of steps.
/// Creates a new `BinomialTreeModel` with a specified number of steps and epsilon.
///
/// # Arguments
///
/// * `steps` - Number of steps in the binomial tree model.
pub fn new(steps: usize) -> Self {
Self { steps }
/// * `epsilon` - Epsilon value for numerical differentiation.
pub fn new(steps: usize, epsilon: f64) -> Self {
Self { steps, epsilon }
}

/// Initializes the prices vector for call or put options.
Expand Down Expand Up @@ -49,6 +52,7 @@ impl BinomialTreeModel {
})
.collect()
}

/// Performs backward induction to calculate option price.
///
/// # Arguments
Expand Down Expand Up @@ -78,7 +82,10 @@ impl BinomialTreeModel {

impl Default for BinomialTreeModel {
fn default() -> Self {
Self { steps: 100 } // Default number of steps is 100
Self {
steps: 100,
epsilon: 1e-5,
} // Default number of steps is 100 and epsilon is 1e-5
}
}

Expand Down Expand Up @@ -130,11 +137,6 @@ impl OptionPricingModel for BinomialTreeModel {
s: params.s * u,
..params.clone()
};
let params = OptionParameters {
s: params.s * d,
..params.clone()
};

let down_params = OptionParameters {
s: params.s * d,
..params.clone()
Expand Down Expand Up @@ -172,6 +174,7 @@ impl OptionPricingModel for BinomialTreeModel {

(delta_up - delta_down) / (0.5 * params.s * (u - d))
}

/// Calculates the theta of the option using the binomial tree model.
///
/// # Arguments
Expand All @@ -182,16 +185,16 @@ impl OptionPricingModel for BinomialTreeModel {
///
/// The calculated theta.
fn theta(&self, params: &OptionParameters) -> f64 {
let epsilon = 1e-5;
let new_params = OptionParameters {
t: params.t - epsilon,
t: params.t - self.epsilon,
..params.clone()
};
let call_price_t1 = self.call_price(params);
let call_price_t2 = self.call_price(&new_params);

(call_price_t2 - call_price_t1) / epsilon
(call_price_t2 - call_price_t1) / self.epsilon
}

/// Calculates the vega of the option using the binomial tree model.
///
/// # Arguments
Expand All @@ -200,17 +203,15 @@ impl OptionPricingModel for BinomialTreeModel {
///
/// # Returns
///
/// The calcula ted vega.
/// The calculated vega.
fn vega(&self, params: &OptionParameters) -> f64 {
let epsilon = 1e-5;

let call_price_sigma1 = self.call_price(params);
let call_price_sigma2 = self.call_price(&OptionParameters {
sigma: params.sigma + epsilon,
sigma: params.sigma + self.epsilon,
..params.clone()
});

(call_price_sigma2 - call_price_sigma1) / epsilon
(call_price_sigma2 - call_price_sigma1) / self.epsilon
}

/// Calculates the rho of the option using the binomial tree model.
Expand All @@ -223,14 +224,14 @@ impl OptionPricingModel for BinomialTreeModel {
///
/// The calculated rho.
fn rho(&self, params: &OptionParameters) -> f64 {
let epsilon = 1e-5;
let new_params = OptionParameters {
r: params.r + epsilon,
r: params.r + self.epsilon,
..params.clone()
};
let call_price_r1 = self.call_price(params);
let call_price_r2 = self.call_price(&new_params);

(call_price_r2 - call_price_r1) / epsilon
(call_price_r2 - call_price_r1) / self.epsilon
}
}

11 changes: 8 additions & 3 deletions core/src/models/garch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ pub struct GarchModel {
pub omega: f64,
pub alpha: f64,
pub beta: f64,
/// Epsilon value for numerical differentiation.
pub epsilon: f64,
}

impl GarchModel {
Expand All @@ -19,12 +21,13 @@ impl GarchModel {
/// * `omega` - GARCH model parameter omega.
/// * `alpha` - GARCH model parameter alpha.
/// * `beta` - GARCH model parameter beta.
pub fn new(steps: usize, omega: f64, alpha: f64, beta: f64) -> Self {
pub fn new(steps: usize, omega: f64, alpha: f64, beta: f64, epsilon: f64) -> Self {
Self {
steps,
omega,
alpha,
beta,
epsilon,
}
}
}
Expand All @@ -36,6 +39,7 @@ impl Default for GarchModel {
omega: 0.1,
alpha: 0.1,
beta: 0.8,
epsilon: 1e-5,
}
}
}
Expand Down Expand Up @@ -217,7 +221,7 @@ impl OptionPricingModel for GarchModel {
///
/// The calculated vega.
fn vega(&self, params: &OptionParameters) -> f64 {
let epsilon = 1e-5;
let epsilon = self.epsilon;
let new_params = OptionParameters {
sigma: params.sigma + epsilon,
..params.clone()
Expand All @@ -238,7 +242,7 @@ impl OptionPricingModel for GarchModel {
///
/// The calculated rho.
fn rho(&self, params: &OptionParameters) -> f64 {
let epsilon = 1e-5;
let epsilon = self.epsilon;
let new_params = OptionParameters {
r: params.r + epsilon,
..params.clone()
Expand All @@ -250,3 +254,4 @@ impl OptionPricingModel for GarchModel {
rho.max(0.0)
}
}

38 changes: 19 additions & 19 deletions core/src/models/monte_carlo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ use rand_distr::StandardNormal;
pub struct MonteCarloModel {
/// The number of simulations to run for the Monte Carlo method.
pub simulations: usize,

/// The epsilon value used for finite difference calculations in Greeks.
pub epsilon: f64,
}

impl OptionPricingModel for MonteCarloModel {
Expand Down Expand Up @@ -70,13 +73,12 @@ impl OptionPricingModel for MonteCarloModel {
///
/// Returns the estimated Delta of the option.
fn delta(&self, params: &OptionParameters) -> f64 {
let epsilon = 0.01;
let mut new_params = params.clone();
new_params.s = params.s + epsilon;
new_params.s = params.s + self.epsilon;
let price_up = self.call_price(&new_params);
new_params.s = params.s - epsilon;
new_params.s = params.s - self.epsilon;
let price_down = self.call_price(&new_params);
(price_up - price_down) / (2.0 * epsilon)
(price_up - price_down) / (2.0 * self.epsilon)
}

/// Calculates the Gamma of the option using Monte Carlo simulation.
Expand All @@ -89,13 +91,12 @@ impl OptionPricingModel for MonteCarloModel {
///
/// Returns the estimated Gamma of the option.
fn gamma(&self, params: &OptionParameters) -> f64 {
let epsilon = 0.01;
let mut new_params = params.clone();
new_params.s = params.s + epsilon;
new_params.s = params.s + self.epsilon;
let delta_up = self.delta(&new_params);
new_params.s = params.s - epsilon;
new_params.s = params.s - self.epsilon;
let delta_down = self.delta(&new_params);
(delta_up - delta_down) / (2.0 * epsilon)
(delta_up - delta_down) / (2.0 * self.epsilon)
}

/// Calculates the Vega of the option using Monte Carlo simulation.
Expand All @@ -108,13 +109,12 @@ impl OptionPricingModel for MonteCarloModel {
///
/// Returns the estimated Vega of the option.
fn vega(&self, params: &OptionParameters) -> f64 {
let epsilon = 0.01;
let mut new_params = params.clone();
new_params.sigma = params.sigma + epsilon;
new_params.sigma = params.sigma + self.epsilon;
let price_up = self.call_price(&new_params);
new_params.sigma = params.sigma - epsilon;
new_params.sigma = params.sigma - self.epsilon;
let price_down = self.call_price(&new_params);
(price_up - price_down) / (2.0 * epsilon)
(price_up - price_down) / (2.0 * self.epsilon)
}

/// Calculates the Theta of the option using Monte Carlo simulation.
Expand All @@ -127,12 +127,12 @@ impl OptionPricingModel for MonteCarloModel {
///
/// Returns the estimated Theta of the option.
fn theta(&self, params: &OptionParameters) -> f64 {
let epsilon = 1.0 / 365.0; // One day
let day_epsilon = 1.0 / 365.0; // One day
let mut new_params = params.clone();
let price_now = self.call_price(params);
new_params.t = params.t - epsilon;
new_params.t = params.t - day_epsilon;
let price_future = self.call_price(&new_params);
(price_future - price_now) / epsilon
(price_future - price_now) / day_epsilon
}

/// Calculates the Rho of the option using Monte Carlo simulation.
Expand All @@ -145,12 +145,12 @@ impl OptionPricingModel for MonteCarloModel {
///
/// Returns the estimated Rho of the option.
fn rho(&self, params: &OptionParameters) -> f64 {
let epsilon = 0.01;
let mut new_params = params.clone();
new_params.r = params.r + epsilon;
new_params.r = params.r + self.epsilon;
let price_up = self.call_price(&new_params);
new_params.r = params.r - epsilon;
new_params.r = params.r - self.epsilon;
let price_down = self.call_price(&new_params);
(price_up - price_down) / (2.0 * epsilon)
(price_up - price_down) / (2.0 * self.epsilon)
}
}

3 changes: 3 additions & 0 deletions core/tests/monte_carlo_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use core::models::{OptionParameters, OptionPricingModel};
fn test_call_price() {
let model = MonteCarloModel {
simulations: 100000,
epsilon: 0.01,
};
let params = OptionParameters {
s: 100.0,
Expand All @@ -23,6 +24,7 @@ fn test_call_price() {
fn test_put_price() {
let model = MonteCarloModel {
simulations: 100000,
epsilon: 0.01,
};
let params = OptionParameters {
s: 100.0,
Expand All @@ -34,3 +36,4 @@ fn test_put_price() {
let put_price = model.put_price(&params);
assert!((put_price - 5.57).abs() < 1.0);
}

0 comments on commit 8d17a79

Please sign in to comment.