Skip to content

Commit 9019283

Browse files
committed
added npv, compound interest and payback period
1 parent 379b934 commit 9019283

File tree

4 files changed

+104
-0
lines changed

4 files changed

+104
-0
lines changed

src/financial/compound_interest.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// compound interest is given by A = P(1+r/n)^nt
2+
// where: A = Final Amount, P = Principal Amount, r = rate of interest,
3+
// n = number of times interest is compounded per year and t = time (in years)
4+
5+
pub fn compound_interest(princpal: f64, rate: f64, comp_per_year: u32, years: f64) -> f64 {
6+
let amount = princpal * (1.00 + rate / comp_per_year as f64).powf(comp_per_year as f64 * years);
7+
return amount;
8+
}
9+
10+
#[cfg(test)]
11+
mod tests {
12+
use super::*;
13+
14+
#[test]
15+
fn test_compound_interest() {
16+
let principal = 1000.0;
17+
let rate = 0.05; // 5% annual interest
18+
let times_per_year = 4; // interest compounded quarterly
19+
let years = 2.0; // 2 years tenure
20+
let result = compound_interest(principal, rate, times_per_year, years);
21+
assert!((result - 1104.486).abs() < 0.001); // expected value rounded up to 3 decimal
22+
// places
23+
}
24+
}

src/financial/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
1+
mod compound_interest;
2+
mod npv;
3+
mod payback;
14
mod present_value;
5+
pub use compound_interest::compound_interest;
6+
pub use npv::npv;
7+
pub use payback;
28
pub use present_value::present_value;

src/financial/npv.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/// Calculates Net Present Value given a vector of cash flows and a discount rate.
2+
/// cash_flows: Vector of f64 representing cash flows for each period.
3+
/// rate: Discount rate as an f64 (e.g., 0.05 for 5%)
4+
5+
pub fn npv(cash_flows: &[f64], rate: f64) -> f64 {
6+
cash_flows
7+
.iter()
8+
.enumerate()
9+
.map(|(t, &cf)| cf / (1.00 + rate).powi(t as i32))
10+
.sum()
11+
}
12+
13+
// tests
14+
15+
#[cfg(test)]
16+
mod tests {
17+
use super::*;
18+
19+
#[test]
20+
fn test_npv_basic() {
21+
let cash_flows = vec![-1000.0, 300.0, 400.0, -50.0];
22+
let rate = 0.10;
23+
let result = npv(&cash_flows, rate);
24+
// Calculated value ≈ -434.25
25+
assert!((result - (-434.25)).abs() < 0.05); // Allow small margin of error
26+
}
27+
28+
#[test]
29+
fn test_npv_zero_rate() {
30+
let cash_flows = vec![100.0, 200.0, -50.0];
31+
let rate = 0.0;
32+
let result = npv(&cash_flows, rate);
33+
assert!((result - 250.0).abs() < 0.05);
34+
}
35+
36+
#[test]
37+
fn test_npv_empty() {
38+
// For empty cash flows: NPV should be 0
39+
let cash_flows: Vec<f64> = vec![];
40+
let rate = 0.05;
41+
let result = npv(&cash_flows, rate);
42+
assert_eq!(result, 0.0);
43+
}
44+
}

src/financial/payback.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/// Returns the payback period in years
2+
/// If investment is not paid back, returns None.
3+
4+
pub fn payback(cash_flow: &[f64]) -> Option<usize> {
5+
let mut total = 0.00;
6+
for (year, &cf) in cash_flow.iter().enumerate() {
7+
total += cf;
8+
if total >= 0.00 {
9+
return Some(year);
10+
}
11+
}
12+
None
13+
}
14+
15+
#[cfg(test)]
16+
mod tests {
17+
use super::*;
18+
19+
#[test]
20+
fn test_payback() {
21+
let cash_flows = vec![-1000.0, 300.0, 400.0, 500.0];
22+
assert_eq!(payback(&cash_flows), Some(3)); // paid back in year 3
23+
}
24+
25+
#[test]
26+
fn test_no_payback() {
27+
let cash_flows = vec![-1000.0, 100.0, 100.0, 100.0];
28+
assert_eq!(payback(&cash_flows), None); // never paid back
29+
}
30+
}

0 commit comments

Comments
 (0)