Skip to content

Commit

Permalink
Use assert_approx_eq crate instead of inhouse.
Browse files Browse the repository at this point in the history
  • Loading branch information
MeetThePatel committed Aug 14, 2024
1 parent 0c86678 commit 16ff157
Show file tree
Hide file tree
Showing 13 changed files with 87 additions and 123 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ rustdoc-args = ["--html-in-header", "katex_header.html", "--cfg", "docsrs"]

[[example]]
name = "black_scholes"

[dev-dependencies]
assert_approx_eq = "1.1.0"
2 changes: 1 addition & 1 deletion src/instruments/options/american_option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::fmt::Display;

use crate::instruments::exercises::{AmericanExercise, Exercise};
use crate::instruments::options::{Option, OptionType};
use crate::instruments::payoffs::{CallPutPayoff, Payoff, VanillaPayoff};
use crate::instruments::payoffs::{Payoff, StrikedPayoff, VanillaPayoff};
use crate::money::Currency;

pub struct AmericanOption<C>
Expand Down
4 changes: 2 additions & 2 deletions src/instruments/options/european_option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::fmt::Display;

use crate::instruments::exercises::{EuropeanExercise, Exercise};
use crate::instruments::options::{Option, OptionType};
use crate::instruments::payoffs::{CallPutPayoff, Payoff, VanillaPayoff};
use crate::instruments::payoffs::{Payoff, StrikedPayoff, VanillaPayoff};
use crate::money::{Currency, Money};

pub struct EuropeanOption<C>
Expand All @@ -23,7 +23,7 @@ where
}

#[must_use]
pub const fn get_strike(&self) -> Money<C> {
pub fn get_strike(&self) -> Money<C> {
self.payoff.get_strike()
}
}
Expand Down
12 changes: 5 additions & 7 deletions src/instruments/payoffs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,19 @@ mod vanilla_payoff;
pub use vanilla_payoff::VanillaPayoff;

use crate::instruments::options::OptionType;
use crate::money::Currency;

pub trait Payoff: std::fmt::Display {
// Type most likely should be Money<N, C>.
// However, in the future, other option types will be implemented, such as percentage strikes.
type PayoffNumberType;

fn get_strike(&self) -> Self::PayoffNumberType;

fn apply(&self, price: Self::PayoffNumberType) -> Self::PayoffNumberType;
}

pub trait CallPutPayoff<C>: Payoff
where
C: Currency,
{
pub trait StrikedPayoff: Payoff {
#[must_use]
fn get_strike(&self) -> Self::PayoffNumberType;

#[must_use]
fn get_option_type(&self) -> OptionType;
}
21 changes: 8 additions & 13 deletions src/instruments/payoffs/vanilla_payoff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use std::marker::PhantomData;
use num::Zero;

use crate::instruments::options::OptionType;
use crate::instruments::payoffs::{CallPutPayoff, Payoff};
use crate::instruments::payoffs::Payoff;
use crate::instruments::payoffs::StrikedPayoff;
use crate::money::{Currency, Money};

#[derive(Debug, Copy, Clone)]
Expand All @@ -30,12 +31,6 @@ where
currency: PhantomData,
}
}

#[must_use]
#[inline]
pub const fn get_strike(&self) -> Money<C> {
self.strike
}
}

impl<C> Display for VanillaPayoff<C>
Expand All @@ -53,10 +48,6 @@ where
{
type PayoffNumberType = Money<C>;

fn get_strike(&self) -> Self::PayoffNumberType {
self.strike
}

fn apply(&self, price: Self::PayoffNumberType) -> Self::PayoffNumberType {
match self.option_type {
OptionType::CALL => {
Expand All @@ -77,10 +68,14 @@ where
}
}

impl<C> CallPutPayoff<C> for VanillaPayoff<C>
impl<C> StrikedPayoff for VanillaPayoff<C>
where
C: Currency,
{
fn get_strike(&self) -> Self::PayoffNumberType {
self.strike
}

fn get_option_type(&self) -> OptionType {
self.option_type
}
Expand All @@ -91,7 +86,7 @@ mod tests {
use crate::{
instruments::{
options::OptionType,
payoffs::{CallPutPayoff, Payoff},
payoffs::{Payoff, StrikedPayoff},
},
money::{currency::USD, Money},
};
Expand Down
19 changes: 10 additions & 9 deletions src/interest_rate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ where

#[cfg(test)]
mod tests {
use assert_approx_eq::assert_approx_eq;
use day_count_conventions::Actual360;

use super::*;
Expand Down Expand Up @@ -200,13 +201,13 @@ mod tests {
);
let dcf1 = DayCountFraction::new(1.0);
// Discount Factor
assert_approx_equal_f64!(simple_rate.discount_factor(&dcf1), 0.952_380_95, 10e-8);
assert_approx_equal_f64!(compound_rate.discount_factor(&dcf1), 0.951_524_27, 10e-8);
assert_approx_equal_f64!(continuous_rate.discount_factor(&dcf1), 0.951_229_42, 10e-8);
assert_approx_eq!(*simple_rate.discount_factor(&dcf1), 0.952_380_95, 10e-8);
assert_approx_eq!(*compound_rate.discount_factor(&dcf1), 0.951_524_27, 10e-8);
assert_approx_eq!(*continuous_rate.discount_factor(&dcf1), 0.951_229_42, 10e-8);

// Implied Interest Rate from Compound Factor
assert_approx_equal_f64!(
implied_rate_from_compound_factor::<USD, _>(
assert_approx_eq!(
*implied_rate_from_compound_factor::<USD, _>(
1.5,
&dcf1,
Actual360,
Expand All @@ -217,8 +218,8 @@ mod tests {
0.5,
10e-8
);
assert_approx_equal_f64!(
implied_rate_from_compound_factor::<USD, Actual360>(
assert_approx_eq!(
*implied_rate_from_compound_factor::<USD, Actual360>(
1.5,
&DayCountFraction::new(1.0),
Actual360,
Expand All @@ -229,8 +230,8 @@ mod tests {
0.426_727_67,
10e-8
);
assert_approx_equal_f64!(
implied_rate_from_compound_factor::<USD, Actual360>(
assert_approx_eq!(
*implied_rate_from_compound_factor::<USD, Actual360>(
1.5,
&DayCountFraction::new(1.0),
Actual360,
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub mod instruments;
pub mod money;

#[macro_use]
pub mod macros;
pub(crate) mod macros;

pub mod interest_rate;
pub mod term_structures;
Expand Down
59 changes: 6 additions & 53 deletions src/macros.rs
Original file line number Diff line number Diff line change
@@ -1,60 +1,13 @@
#[macro_export]
macro_rules! assert_approx_equal_f64 {
#[allow(unused_macros)]
macro_rules! assert_approx_equal_money {
($x:expr, $y:expr, $d:expr) => {
assert!(
((ordered_float::OrderedFloat::<f64>::from($x)
- ordered_float::OrderedFloat::<f64>::from($y))
.le(&ordered_float::OrderedFloat::<f64>::from($d)))
&& ((ordered_float::OrderedFloat::<f64>::from($y)
- ordered_float::OrderedFloat::<f64>::from($x))
.le(&ordered_float::OrderedFloat::<f64>::from($d))),
"\nLeft: \t\t{}, \nRight: \t\t{}, \nPrecision: \t{}\n",
$x,
$y,
$d
);
};
}
pub use assert_approx_equal_f64;

#[macro_export]
macro_rules! assert_approx_equal_f32 {
($x:expr, $y:expr, $d:expr) => {
assert!(
(ordered_float::OrderedFloat::<f32>::from($x)
- ordered_float::OrderedFloat::<f32>::from($y))
.le(ordered_float::OrderedFloat::<f32>::from($d))
&& ((ordered_float::OrderedFloat::<f32>::from($y)
- ordered_float::OrderedFloat::<f32>::from($x))
.le(ordered_float::OrderedFloat::<f32>::from($d))),
"\nLeft: \t\t{}, \nRight: \t\t{}, \nPrecision: \t{}\n",
$x,
$y,
$d
);
};
}
pub use assert_approx_equal_f32;

#[macro_export]
macro_rules! assert_approx_equal_Money {
($x:expr, $y:expr, $d:expr) => {
assert!(
((ordered_float::OrderedFloat::<f64>::from(($x - $y).amount))
.le(&ordered_float::OrderedFloat::<f64>::from($d)))
&& ((ordered_float::OrderedFloat::<f64>::from(($y - $x).amount))
.le(&ordered_float::OrderedFloat::<f64>::from($d))),
"\nLeft: \t\t{}, \nRight: \t\t{}, \nPrecision: \t{}\n",
$x,
$y,
$d
);
assert_eq!($x.get_currency_name(), $y.get_currency_name());
assert_approx_eq::assert_approx_eq!($x.amount, $y.amount, $d);
};
}
pub use assert_approx_equal_Money;
#[allow(unused_imports)]
pub(crate) use assert_approx_equal_money;

#[macro_export]
macro_rules! any_true {
() => {
None
Expand All @@ -77,4 +30,4 @@ macro_rules! any_true {
}
};
}
pub use any_true;
pub(crate) use any_true;
10 changes: 5 additions & 5 deletions src/money/exchange_rate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ where
#[cfg(test)]
mod tests {

use crate::macros::assert_approx_equal_Money;
use crate::macros::assert_approx_equal_money;
use crate::money::currency::{EUR, USD};
use crate::money::Money;

Expand All @@ -80,17 +80,17 @@ mod tests {
let m1: Money<USD> = Money::new(10.0);
let rate: ExchangeRate<EUR, USD> = ExchangeRate::new(1.08372);

let expected = Money::new(9.227_475_731_738_826);
assert_approx_equal_Money!(rate.convert_to_base(&m1), expected, 10e-8);
let expected: Money<EUR> = Money::new(9.227_475_731_738_826);
assert_approx_equal_money!(rate.convert_to_base(&m1), expected, 10e-8);
}

#[test]
fn test_base_to_quote() {
let m1: Money<EUR> = Money::new(10.0);
let rate: ExchangeRate<EUR, USD> = ExchangeRate::new(1.08372);

let expected = Money::new(10.8372);
assert_approx_equal_Money!(rate.convert_to_quote(&m1), expected, 10e-8);
let expected: Money<USD> = Money::new(10.8372);
assert_approx_equal_money!(rate.convert_to_quote(&m1), expected, 10e-8);
}

#[test]
Expand Down
28 changes: 17 additions & 11 deletions src/money/exchange_rate_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,17 @@ impl<'a> Display for ExchangeRateManager<'a> {

#[cfg(test)]
mod tests {
use crate::assert_approx_equal_f64;
use crate::macros::assert_approx_equal_Money;
use crate::money::{
currency::{EUR, GBP, JPY, USD},
ExchangeRate, ExchangeRateManagerError, Money,
use assert_approx_eq::assert_approx_eq;

use crate::{
macros::assert_approx_equal_money,
money::{
currency::{EUR, GBP, JPY, USD},
ExchangeRate, ExchangeRateManagerError, Money,
},
};

use super::ExchangeRateManager;
use crate::money::ExchangeRateManager;

#[test]
fn test_exchange_rate_manager_operations() {
Expand Down Expand Up @@ -213,12 +216,13 @@ mod tests {

// Test get.
let rate = manager.get(&GBP::default(), &USD::default()).unwrap();
assert_approx_equal_f64!(rate.rate, 1.28510, 10e-8);
// assert_approx_equal_f64!(rate.rate, 1.28510, 10e-8);
assert_approx_eq!(rate.rate, 1.28510, 10e-8);

// Test convert to base.
let m1: Money<USD> = Money::new(1.0);
let expected: Money<GBP> = Money::new(0.778_149_56);
assert_approx_equal_Money!(
assert_approx_equal_money!(
manager.convert(&m1, &GBP::default()).unwrap(),
expected,
10e-7
Expand All @@ -227,7 +231,7 @@ mod tests {
// Test convert to quote.
let m2: Money<GBP> = Money::new(1.0);
let expected: Money<USD> = Money::new(1.28510);
assert_approx_equal_Money!(
assert_approx_equal_money!(
manager.convert(&m2, &USD::default()).unwrap(),
expected,
10e-7
Expand All @@ -237,11 +241,13 @@ mod tests {
let gbpusd: ExchangeRate<GBP, USD> = ExchangeRate::new(1.28512);
manager.update(&gbpusd);
let rate = manager.get(&GBP::default(), &USD::default()).unwrap();
assert_approx_equal_f64!(rate.rate, 1.28512_f64, 10e-8);
// assert_approx_equal_f64!(rate.rate, 1.28512_f64, 10e-8);
assert_approx_eq!(rate.rate, 1.28512_f64, 10e-8);

// Test remove.
let rate = manager.remove(&GBP::default(), &USD::default()).unwrap();
assert_approx_equal_f64!(rate.rate, 1.28512_f64, 10e-8);
// assert_approx_equal_f64!(rate.rate, 1.28512_f64, 10e-8);
assert_approx_eq!(rate.rate, 1.28512_f64, 10e-8);

// Test clear.
manager.clear();
Expand Down
Loading

0 comments on commit 16ff157

Please sign in to comment.