Skip to content

Commit 8e9dbdb

Browse files
create present value module
add documentation in readme.md
1 parent 603db05 commit 8e9dbdb

File tree

3 files changed

+59
-1
lines changed

3 files changed

+59
-1
lines changed

src/financial/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
11
## Financial Algorithms
2+
### [Present-Value Algorithm](./present_value.rs)
3+
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
4+
5+
[present-value-wiki]: https://en.wikipedia.org/wiki/Present_value

src/financial/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
mod price_plus_tax;
2-
2+
mod present_value;
33
pub use price_plus_tax::price_plus_tax;
4+
pub use present_value::present_value;
5+

src/financial/present_value.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#[derive(PartialEq, Eq,Debug)]
2+
pub enum PresentValueError{
3+
NegetiveDiscount,
4+
EmptyCashFlow
5+
}
6+
7+
8+
pub fn present_value(discount_rate: f64, cash_flows: Vec<f64>) -> Result<f64, PresentValueError> {
9+
if discount_rate < 0.0 {
10+
return Err(PresentValueError::NegetiveDiscount);
11+
}
12+
if cash_flows.is_empty() {
13+
return Err(PresentValueError::EmptyCashFlow);
14+
}
15+
16+
let present_value = cash_flows.iter().enumerate()
17+
.map(|(i, &cash_flow)| cash_flow / (1.0 + discount_rate).powi(i as i32))
18+
.sum::<f64>();
19+
20+
Ok((present_value * 100.0).round() / 100.0)
21+
}
22+
23+
#[cfg(test)]
24+
mod tests {
25+
use super::*;
26+
27+
#[test]
28+
fn test_present_value() {
29+
30+
assert_eq!(4.69,present_value(0.13, vec![10.0, 20.70, -293.0, 297.0]).unwrap());
31+
32+
assert_eq!( -42739.63,present_value(0.07, vec![-109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap());
33+
34+
assert_eq!(175519.15,present_value(0.07, vec![109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap());
35+
}
36+
37+
#[test]
38+
fn test_present_value_negative_discount_rate() {
39+
assert_eq!(PresentValueError::NegetiveDiscount,present_value(-1.0, vec![10.0, 20.70, -293.0, 297.0]).unwrap_err());
40+
41+
}
42+
43+
#[test]
44+
fn test_present_value_empty_cash_flow() {
45+
assert_eq!(PresentValueError::EmptyCashFlow,present_value(1.0, vec![]).unwrap_err());
46+
}
47+
48+
#[test]
49+
fn test_present_value_zero_discount_rate() {
50+
assert_eq!(184924.55,present_value(0.0, vec![109129.39, 30923.23, 15098.93, 29734.0,39.0]).unwrap());
51+
}
52+
}

0 commit comments

Comments
 (0)