Skip to content

Commit abff887

Browse files
create financial/price_plus_tax function (#829)
* create financial/price_plus_tax function * run cargo fmt * add readme.md in financial tax * create present value module add documentation in readme.md * run fmt command * seperate round function in present_value module * remove price_plus_tx use macro for test * use fmt and clippy * add document to present_value --------- Co-authored-by: Piotr Idzik <[email protected]>
1 parent 5947a3f commit abff887

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed

src/financial/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
mod present_value;
2+
pub use present_value::present_value;

src/financial/present_value.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/// In economics and finance, present value (PV), also known as present discounted value,
2+
/// is the value of an expected income stream determined as of the date of valuation.
3+
///
4+
/// -> Uncyclopedia reference: https://en.wikipedia.org/wiki/Present_value
5+
6+
#[derive(PartialEq, Eq, Debug)]
7+
pub enum PresentValueError {
8+
NegetiveDiscount,
9+
EmptyCashFlow,
10+
}
11+
12+
pub fn present_value(discount_rate: f64, cash_flows: Vec<f64>) -> Result<f64, PresentValueError> {
13+
if discount_rate < 0.0 {
14+
return Err(PresentValueError::NegetiveDiscount);
15+
}
16+
if cash_flows.is_empty() {
17+
return Err(PresentValueError::EmptyCashFlow);
18+
}
19+
20+
let present_value = cash_flows
21+
.iter()
22+
.enumerate()
23+
.map(|(i, &cash_flow)| cash_flow / (1.0 + discount_rate).powi(i as i32))
24+
.sum::<f64>();
25+
26+
Ok(round(present_value))
27+
}
28+
29+
fn round(value: f64) -> f64 {
30+
(value * 100.0).round() / 100.0
31+
}
32+
33+
#[cfg(test)]
34+
mod tests {
35+
use super::*;
36+
37+
macro_rules! test_present_value {
38+
($($name:ident: $inputs:expr,)*) => {
39+
$(
40+
#[test]
41+
fn $name() {
42+
let ((discount_rate,cash_flows), expected) = $inputs;
43+
assert_eq!(present_value(discount_rate,cash_flows).unwrap(), expected);
44+
}
45+
)*
46+
}
47+
}
48+
49+
macro_rules! test_present_value_Err {
50+
($($name:ident: $inputs:expr,)*) => {
51+
$(
52+
#[test]
53+
fn $name() {
54+
let ((discount_rate,cash_flows), expected) = $inputs;
55+
assert_eq!(present_value(discount_rate,cash_flows).unwrap_err(), expected);
56+
}
57+
)*
58+
}
59+
}
60+
61+
macro_rules! test_round {
62+
($($name:ident: $inputs:expr,)*) => {
63+
$(
64+
#[test]
65+
fn $name() {
66+
let (input, expected) = $inputs;
67+
assert_eq!(round(input), expected);
68+
}
69+
)*
70+
}
71+
}
72+
73+
test_present_value! {
74+
general_inputs1:((0.13, vec![10.0, 20.70, -293.0, 297.0]),4.69),
75+
general_inputs2:((0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0, 39.0]),-42739.63),
76+
general_inputs3:((0.07, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]), 175519.15),
77+
zero_input:((0.0, vec![109129.39, 30923.23, 15098.93, 29734.0, 39.0]), 184924.55),
78+
79+
}
80+
81+
test_present_value_Err! {
82+
negative_discount_rate:((-1.0, vec![10.0, 20.70, -293.0, 297.0]), PresentValueError::NegetiveDiscount),
83+
empty_cash_flow:((1.0, vec![]), PresentValueError::EmptyCashFlow),
84+
85+
}
86+
test_round! {
87+
test1:(0.55434, 0.55),
88+
test2:(10.453, 10.45),
89+
test3:(1111_f64, 1111_f64),
90+
}
91+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub mod compression;
88
pub mod conversions;
99
pub mod data_structures;
1010
pub mod dynamic_programming;
11+
pub mod financial;
1112
pub mod general;
1213
pub mod geometry;
1314
pub mod graph;

0 commit comments

Comments
 (0)