From 910ecce97286b666f7e68f7f8390cf1bc41a3bc6 Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Sun, 20 Oct 2024 16:10:01 +0330 Subject: [PATCH 1/9] create financial/price_plus_tax function --- src/financial/mod.rs | 3 +++ src/financial/price_plus_tax.rs | 16 ++++++++++++++++ src/lib.rs | 1 + 3 files changed, 20 insertions(+) create mode 100644 src/financial/mod.rs create mode 100644 src/financial/price_plus_tax.rs diff --git a/src/financial/mod.rs b/src/financial/mod.rs new file mode 100644 index 00000000000..8d6778ba92c --- /dev/null +++ b/src/financial/mod.rs @@ -0,0 +1,3 @@ +mod price_plus_tax; + +pub use price_plus_tax::price_plus_tax; \ No newline at end of file diff --git a/src/financial/price_plus_tax.rs b/src/financial/price_plus_tax.rs new file mode 100644 index 00000000000..4e0c2d5842a --- /dev/null +++ b/src/financial/price_plus_tax.rs @@ -0,0 +1,16 @@ +pub fn price_plus_tax(price: f64, tax_rate: f64) -> f64{ + price * (1 as f64 + tax_rate) +} + + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_price_plus_tax() { + assert_eq!(131.775,price_plus_tax(125.50, 0.05)); + assert_eq!( 125.0,price_plus_tax(100.0, 0.25)); + } +} diff --git a/src/lib.rs b/src/lib.rs index db12b52b6dd..db33c7157ee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ pub mod number_theory; pub mod searching; pub mod sorting; pub mod string; +pub mod financial; #[cfg(test)] mod tests { From 3901d8bc85ef0f497ae491db806da53e3f97929b Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Sat, 26 Oct 2024 09:49:05 +0330 Subject: [PATCH 2/9] run cargo fmt --- src/financial/mod.rs | 2 +- src/financial/price_plus_tax.rs | 12 +++++------- src/lib.rs | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/financial/mod.rs b/src/financial/mod.rs index 8d6778ba92c..42436d54277 100644 --- a/src/financial/mod.rs +++ b/src/financial/mod.rs @@ -1,3 +1,3 @@ mod price_plus_tax; -pub use price_plus_tax::price_plus_tax; \ No newline at end of file +pub use price_plus_tax::price_plus_tax; diff --git a/src/financial/price_plus_tax.rs b/src/financial/price_plus_tax.rs index 4e0c2d5842a..8b88c661db6 100644 --- a/src/financial/price_plus_tax.rs +++ b/src/financial/price_plus_tax.rs @@ -1,8 +1,6 @@ -pub fn price_plus_tax(price: f64, tax_rate: f64) -> f64{ - price * (1 as f64 + tax_rate) -} - - +pub fn price_plus_tax(price: f64, tax_rate: f64) -> f64 { + price * (1_f64 + tax_rate) +} #[cfg(test)] mod tests { @@ -10,7 +8,7 @@ mod tests { #[test] fn test_price_plus_tax() { - assert_eq!(131.775,price_plus_tax(125.50, 0.05)); - assert_eq!( 125.0,price_plus_tax(100.0, 0.25)); + assert_eq!(131.775, price_plus_tax(125.50, 0.05)); + assert_eq!(125.0, price_plus_tax(100.0, 0.25)); } } diff --git a/src/lib.rs b/src/lib.rs index db33c7157ee..fb64d09282a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ pub mod compression; pub mod conversions; pub mod data_structures; pub mod dynamic_programming; +pub mod financial; pub mod general; pub mod geometry; pub mod graph; @@ -19,7 +20,6 @@ pub mod number_theory; pub mod searching; pub mod sorting; pub mod string; -pub mod financial; #[cfg(test)] mod tests { From 603db051950eaec152e28a1f6ad7c3d9add1189c Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Wed, 30 Oct 2024 09:21:54 +0330 Subject: [PATCH 3/9] add readme.md in financial tax --- src/financial/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/financial/README.md diff --git a/src/financial/README.md b/src/financial/README.md new file mode 100644 index 00000000000..0b74d6833bd --- /dev/null +++ b/src/financial/README.md @@ -0,0 +1 @@ +## Financial Algorithms From 8e9dbdbbfff388696c7cc7f27a23ce8df6f3c40f Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Wed, 30 Oct 2024 10:08:55 +0330 Subject: [PATCH 4/9] create present value module add documentation in readme.md --- src/financial/README.md | 4 +++ src/financial/mod.rs | 4 ++- src/financial/present_value.rs | 52 ++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/financial/present_value.rs diff --git a/src/financial/README.md b/src/financial/README.md index 0b74d6833bd..8ae311e80d3 100644 --- a/src/financial/README.md +++ b/src/financial/README.md @@ -1 +1,5 @@ ## Financial Algorithms +### [Present-Value Algorithm](./present_value.rs) +From [Wikipedia][present-value-wiki]: In economics and finance, present value (PV), also known as present discounted value, is the value of an expected income stream determined as of the date of valuation. The present value is usually less than the future value because money has interest-earning potential, a characteristic referred to as the time value of money, except during times of negative interest rates, when the present value will be equal or more than the future value + +[present-value-wiki]: https://en.wikipedia.org/wiki/Present_value diff --git a/src/financial/mod.rs b/src/financial/mod.rs index 42436d54277..6baa23b2a32 100644 --- a/src/financial/mod.rs +++ b/src/financial/mod.rs @@ -1,3 +1,5 @@ mod price_plus_tax; - +mod present_value; pub use price_plus_tax::price_plus_tax; +pub use present_value::present_value; + diff --git a/src/financial/present_value.rs b/src/financial/present_value.rs new file mode 100644 index 00000000000..569f1a930e5 --- /dev/null +++ b/src/financial/present_value.rs @@ -0,0 +1,52 @@ +#[derive(PartialEq, Eq,Debug)] +pub enum PresentValueError{ + NegetiveDiscount, + EmptyCashFlow +} + + +pub fn present_value(discount_rate: f64, cash_flows: Vec) -> Result { + if discount_rate < 0.0 { + return Err(PresentValueError::NegetiveDiscount); + } + if cash_flows.is_empty() { + return Err(PresentValueError::EmptyCashFlow); + } + + let present_value = cash_flows.iter().enumerate() + .map(|(i, &cash_flow)| cash_flow / (1.0 + discount_rate).powi(i as i32)) + .sum::(); + + Ok((present_value * 100.0).round() / 100.0) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_present_value() { + + assert_eq!(4.69,present_value(0.13, vec![10.0, 20.70, -293.0, 297.0]).unwrap()); + + assert_eq!( -42739.63,present_value(0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap()); + + assert_eq!(175519.15,present_value(0.07, vec![109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap()); + } + + #[test] + fn test_present_value_negative_discount_rate() { + assert_eq!(PresentValueError::NegetiveDiscount,present_value(-1.0, vec![10.0, 20.70, -293.0, 297.0]).unwrap_err()); + + } + + #[test] + fn test_present_value_empty_cash_flow() { + assert_eq!(PresentValueError::EmptyCashFlow,present_value(1.0, vec![]).unwrap_err()); + } + + #[test] + fn test_present_value_zero_discount_rate() { + assert_eq!(184924.55,present_value(0.0, vec![109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap()); + } +} From e6392530689cd29cb4744774ab0525ac8bc705ee Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Wed, 30 Oct 2024 10:14:55 +0330 Subject: [PATCH 5/9] run fmt command --- src/financial/mod.rs | 5 ++-- src/financial/present_value.rs | 43 ++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/financial/mod.rs b/src/financial/mod.rs index 6baa23b2a32..0cb97032f56 100644 --- a/src/financial/mod.rs +++ b/src/financial/mod.rs @@ -1,5 +1,4 @@ -mod price_plus_tax; mod present_value; -pub use price_plus_tax::price_plus_tax; +mod price_plus_tax; pub use present_value::present_value; - +pub use price_plus_tax::price_plus_tax; diff --git a/src/financial/present_value.rs b/src/financial/present_value.rs index 569f1a930e5..cb19ea236f8 100644 --- a/src/financial/present_value.rs +++ b/src/financial/present_value.rs @@ -1,10 +1,9 @@ -#[derive(PartialEq, Eq,Debug)] -pub enum PresentValueError{ +#[derive(PartialEq, Eq, Debug)] +pub enum PresentValueError { NegetiveDiscount, - EmptyCashFlow + EmptyCashFlow, } - pub fn present_value(discount_rate: f64, cash_flows: Vec) -> Result { if discount_rate < 0.0 { return Err(PresentValueError::NegetiveDiscount); @@ -13,7 +12,9 @@ pub fn present_value(discount_rate: f64, cash_flows: Vec) -> Result(); @@ -26,27 +27,43 @@ mod tests { #[test] fn test_present_value() { + assert_eq!( + 4.69, + present_value(0.13, vec![10.0, 20.70, -293.0, 297.0]).unwrap() + ); - assert_eq!(4.69,present_value(0.13, vec![10.0, 20.70, -293.0, 297.0]).unwrap()); - - assert_eq!( -42739.63,present_value(0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap()); + assert_eq!( + -42739.63, + present_value(0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0, 39.0]).unwrap() + ); - assert_eq!(175519.15,present_value(0.07, vec![109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap()); + assert_eq!( + 175519.15, + present_value(0.07, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]).unwrap() + ); } #[test] fn test_present_value_negative_discount_rate() { - assert_eq!(PresentValueError::NegetiveDiscount,present_value(-1.0, vec![10.0, 20.70, -293.0, 297.0]).unwrap_err()); - + assert_eq!( + PresentValueError::NegetiveDiscount, + present_value(-1.0, vec![10.0, 20.70, -293.0, 297.0]).unwrap_err() + ); } #[test] fn test_present_value_empty_cash_flow() { - assert_eq!(PresentValueError::EmptyCashFlow,present_value(1.0, vec![]).unwrap_err()); + assert_eq!( + PresentValueError::EmptyCashFlow, + present_value(1.0, vec![]).unwrap_err() + ); } #[test] fn test_present_value_zero_discount_rate() { - assert_eq!(184924.55,present_value(0.0, vec![109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap()); + assert_eq!( + 184924.55, + present_value(0.0, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]).unwrap() + ); } } From 14491c74b3534015b7141dbd727132902f246171 Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Sat, 2 Nov 2024 15:03:29 +0330 Subject: [PATCH 6/9] seperate round function in present_value module --- src/financial/README.md | 5 ----- src/financial/present_value.rs | 28 +++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 6 deletions(-) delete mode 100644 src/financial/README.md diff --git a/src/financial/README.md b/src/financial/README.md deleted file mode 100644 index 8ae311e80d3..00000000000 --- a/src/financial/README.md +++ /dev/null @@ -1,5 +0,0 @@ -## Financial Algorithms -### [Present-Value Algorithm](./present_value.rs) -From [Wikipedia][present-value-wiki]: In economics and finance, present value (PV), also known as present discounted value, is the value of an expected income stream determined as of the date of valuation. The present value is usually less than the future value because money has interest-earning potential, a characteristic referred to as the time value of money, except during times of negative interest rates, when the present value will be equal or more than the future value - -[present-value-wiki]: https://en.wikipedia.org/wiki/Present_value diff --git a/src/financial/present_value.rs b/src/financial/present_value.rs index cb19ea236f8..096c52a10c0 100644 --- a/src/financial/present_value.rs +++ b/src/financial/present_value.rs @@ -18,7 +18,11 @@ pub fn present_value(discount_rate: f64, cash_flows: Vec) -> Result(); - Ok((present_value * 100.0).round() / 100.0) + Ok(round(present_value)) +} + +fn round(value:f64)->f64{ + ( value * 100.0).round() / 100.0 } #[cfg(test)] @@ -66,4 +70,26 @@ mod tests { present_value(0.0, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]).unwrap() ); } + #[test] + fn test_round_function() { + + assert_eq!( + 0.55, + round(0.55434) + ); + + assert_eq!( + 10.45, + round(10.453) + ); + + + assert_eq!( + 1111_f64, + round(1111_f64) + ); + + + } + } From b9919e54bb3ef003246602b67b5e16be089abb75 Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Sat, 2 Nov 2024 16:46:45 +0330 Subject: [PATCH 7/9] remove price_plus_tx use macro for test --- src/financial/mod.rs | 2 - src/financial/present_value.rs | 98 ++++++++++++++++----------------- src/financial/price_plus_tax.rs | 14 ----- 3 files changed, 46 insertions(+), 68 deletions(-) delete mode 100644 src/financial/price_plus_tax.rs diff --git a/src/financial/mod.rs b/src/financial/mod.rs index 0cb97032f56..89b36bfa5e0 100644 --- a/src/financial/mod.rs +++ b/src/financial/mod.rs @@ -1,4 +1,2 @@ mod present_value; -mod price_plus_tax; pub use present_value::present_value; -pub use price_plus_tax::price_plus_tax; diff --git a/src/financial/present_value.rs b/src/financial/present_value.rs index 096c52a10c0..dd7cbfb9143 100644 --- a/src/financial/present_value.rs +++ b/src/financial/present_value.rs @@ -25,71 +25,65 @@ fn round(value:f64)->f64{ ( value * 100.0).round() / 100.0 } + #[cfg(test)] mod tests { use super::*; - #[test] - fn test_present_value() { - assert_eq!( - 4.69, - present_value(0.13, vec![10.0, 20.70, -293.0, 297.0]).unwrap() - ); - - assert_eq!( - -42739.63, - present_value(0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0, 39.0]).unwrap() - ); - - assert_eq!( - 175519.15, - present_value(0.07, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]).unwrap() - ); + macro_rules! test_present_value { + ($($name:ident: $inputs:expr,)*) => { + $( + #[test] + fn $name() { + let ((discount_rate,cash_flows), expected) = $inputs; + assert_eq!(present_value(discount_rate,cash_flows).unwrap(), expected); + } + )* + } } - #[test] - fn test_present_value_negative_discount_rate() { - assert_eq!( - PresentValueError::NegetiveDiscount, - present_value(-1.0, vec![10.0, 20.70, -293.0, 297.0]).unwrap_err() - ); + macro_rules! test_present_value_Err { + ($($name:ident: $inputs:expr,)*) => { + $( + #[test] + fn $name() { + let ((discount_rate,cash_flows), expected) = $inputs; + assert_eq!(present_value(discount_rate,cash_flows).unwrap_err(), expected); + } + )* + } } - #[test] - fn test_present_value_empty_cash_flow() { - assert_eq!( - PresentValueError::EmptyCashFlow, - present_value(1.0, vec![]).unwrap_err() - ); + macro_rules! test_round { + ($($name:ident: $inputs:expr,)*) => { + $( + #[test] + fn $name() { + let (input, expected) = $inputs; + assert_eq!(round(input), expected); + } + )* + } } - #[test] - fn test_present_value_zero_discount_rate() { - assert_eq!( - 184924.55, - present_value(0.0, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]).unwrap() - ); - } - #[test] - fn test_round_function() { - - assert_eq!( - 0.55, - round(0.55434) - ); - assert_eq!( - 10.45, - round(10.453) - ); + test_present_value!{ + general_inputs1:((0.13, vec![10.0, 20.70, -293.0, 297.0]),4.69), + general_inputs2:((0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0, 39.0]),-42739.63), + general_inputs3:((0.07, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]), 175519.15), + zero_input:((0.0, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]), 184924.55), - - assert_eq!( - 1111_f64, - round(1111_f64) - ); + } + test_present_value_Err!{ + negative_discount_rate:((-1.0, vec![10.0, 20.70, -293.0, 297.0]), PresentValueError::NegetiveDiscount), + empty_cash_flow:((1.0, vec![]), PresentValueError::EmptyCashFlow), } - + test_round!{ + test1:(0.55434, 0.55), + test2:(10.453, 10.45), + test3:(1111_f64, 1111_f64), + } } + diff --git a/src/financial/price_plus_tax.rs b/src/financial/price_plus_tax.rs deleted file mode 100644 index 8b88c661db6..00000000000 --- a/src/financial/price_plus_tax.rs +++ /dev/null @@ -1,14 +0,0 @@ -pub fn price_plus_tax(price: f64, tax_rate: f64) -> f64 { - price * (1_f64 + tax_rate) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_price_plus_tax() { - assert_eq!(131.775, price_plus_tax(125.50, 0.05)); - assert_eq!(125.0, price_plus_tax(100.0, 0.25)); - } -} From b38be350b492d02687f91098e22674df5ba2f559 Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Sat, 2 Nov 2024 16:47:30 +0330 Subject: [PATCH 8/9] use fmt and clippy --- src/financial/present_value.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/financial/present_value.rs b/src/financial/present_value.rs index dd7cbfb9143..3d1aa1f2f0c 100644 --- a/src/financial/present_value.rs +++ b/src/financial/present_value.rs @@ -21,11 +21,10 @@ pub fn present_value(discount_rate: f64, cash_flows: Vec) -> Resultf64{ - ( value * 100.0).round() / 100.0 +fn round(value: f64) -> f64 { + (value * 100.0).round() / 100.0 } - #[cfg(test)] mod tests { use super::*; @@ -66,8 +65,7 @@ mod tests { } } - - test_present_value!{ + test_present_value! { general_inputs1:((0.13, vec![10.0, 20.70, -293.0, 297.0]),4.69), general_inputs2:((0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0, 39.0]),-42739.63), general_inputs3:((0.07, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]), 175519.15), @@ -75,15 +73,14 @@ mod tests { } - test_present_value_Err!{ + test_present_value_Err! { negative_discount_rate:((-1.0, vec![10.0, 20.70, -293.0, 297.0]), PresentValueError::NegetiveDiscount), empty_cash_flow:((1.0, vec![]), PresentValueError::EmptyCashFlow), } - test_round!{ + test_round! { test1:(0.55434, 0.55), test2:(10.453, 10.45), test3:(1111_f64, 1111_f64), } } - From 7f5b65960fc05b8d406ce8e0020a21b4eee315b0 Mon Sep 17 00:00:00 2001 From: alireza_sariri Date: Sun, 3 Nov 2024 09:46:05 +0330 Subject: [PATCH 9/9] add document to present_value --- src/financial/present_value.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/financial/present_value.rs b/src/financial/present_value.rs index 3d1aa1f2f0c..5294b71758c 100644 --- a/src/financial/present_value.rs +++ b/src/financial/present_value.rs @@ -1,3 +1,8 @@ +/// In economics and finance, present value (PV), also known as present discounted value, +/// is the value of an expected income stream determined as of the date of valuation. +/// +/// -> Wikipedia reference: https://en.wikipedia.org/wiki/Present_value + #[derive(PartialEq, Eq, Debug)] pub enum PresentValueError { NegetiveDiscount,