Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create financial/price_plus_tax function #829

Merged
merged 11 commits into from
Nov 4, 2024
2 changes: 2 additions & 0 deletions src/financial/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod present_value;
pub use present_value::present_value;
91 changes: 91 additions & 0 deletions src/financial/present_value.rs
vil02 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/// 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,
EmptyCashFlow,
}

pub fn present_value(discount_rate: f64, cash_flows: Vec<f64>) -> Result<f64, PresentValueError> {
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::<f64>();

Ok(round(present_value))
}

fn round(value: f64) -> f64 {
(value * 100.0).round() / 100.0
}

#[cfg(test)]
mod tests {
use super::*;

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);
}
)*
}
}

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);
}
)*
}
}

macro_rules! test_round {
($($name:ident: $inputs:expr,)*) => {
$(
#[test]
fn $name() {
let (input, expected) = $inputs;
assert_eq!(round(input), expected);
}
)*
}
}

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),

}

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),
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down