rust_finprim 0.5.1

Various finance and accounting calculations/formulas implemented Rust
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use rust_finprim::derivatives::{npv_prime_r, pv_prime_r};
use rust_finprim::tvm::npv;
use rust_finprim::FloatLike;

// NPV old
pub fn npv_old<T: FloatLike>(rate: T, cash_flows: &[T]) -> T {
    cash_flows
        .iter()
        .enumerate()
        .map(|(t, &cf)| cf / (T::one() + rate).powf(T::from_usize(t)))
        .sum()
}

// NPV'(r) Niave
pub fn npv_prime_r_niave<T: FloatLike>(rate: T, cash_flows: &[T]) -> T {
    cash_flows
        .iter()
        .enumerate()
        .map(|(t, &cf)| pv_prime_r(rate, T::from_usize(t), cf))
        .sum()
}

fn criterion_benchmark(c: &mut Criterion) {
    let rate = 0.1; // 10% discount rate

    // Long cash flow
    let cash_flow: Vec<f64> = vec![
        -100.0, 50.0, 40.0, 30.0, 20.0, 10.0, 5.0, 2.0, 1.0, 0.5, 0.1, 0.05, 0.01, 0.005, 0.001, 0.0005, 0.0001,
        0.00005, 0.00001, 0.000005, 0.000001, 10000.0, 5000.0, 2000.0, 1000.0, 500.0, 200.0, 100.0, 50.0, 1000000.0,
        500000.0, 200000.0, 100000.0, 50000.0, 20000.0, 10000.0, 500000.0, 20000.0, 10000.0, 5000.0, 2000.0, 1000.0,
        500.0, 20.0, 10.0, 5.0, 2.0, 1.0, 0.5, 0.1, 0.05, 0.01, 0.005, 0.001, 50000.0, 25000.0, 10000.0, 5000.0,
        2000.0, 1000.0, 500.0, 200.0, 100.0, 50.0, 20.0, 10.0, 5.0, 2.0, 1.0, 0.5, 0.1, 0.05, -100.0, 50.0, 40.0, 30.0,
        20.0, 10.0, 5.0, 2.0, 1.0, 0.5, 0.1, 0.05, 0.01, 0.005, 0.001, 0.0005, 0.0001, 0.00005, 0.00001, 0.000005,
        0.000001, 10000.0, 5000.0, 2000.0, 1000.0, 500.0, 200.0, 100.0, 50.0, 1000000.0, 500000.0, 200000.0, 100000.0,
        50000.0, 20000.0, 10000.0, 500000.0, 20000.0, 10000.0, 5000.0, 2000.0, 1000.0, 500.0, 20.0, 10.0, 5.0, 2.0,
        1.0, 0.5, 0.1, 0.05, 0.01, 0.005, 0.001, 50000.0, 25000.0, 10000.0, 5000.0, 2000.0, 1000.0, 500.0, 200.0,
        100.0, 50.0, 20.0, 10.0, 5.0, 2.0, 1.0, 0.5, 0.1, 0.05, -100.0, 50.0, 40.0, 30.0, 20.0, 10.0, 5.0, 2.0, 1.0,
        0.5, 0.1, 0.05, 0.01, 0.005, 0.001, 0.0005, 0.0001, 0.00005, 0.00001, 0.000005, 0.000001, 10000.0, 5000.0,
        2000.0, 1000.0, 500.0, 200.0, 100.0, 50.0, 1000000.0, 500000.0, 200000.0, 100000.0, 50000.0, 20000.0, 10000.0,
        500000.0, 20000.0, 10000.0, 5000.0, 2000.0, 1000.0, 500.0, 20.0, 10.0, 5.0, 2.0, 1.0, 0.5, 0.1, 0.05, 0.01,
        0.005, 0.001, 50000.0, 25000.0, 10000.0, 5000.0, 2000.0, 1000.0, 500.0, 200.0, 100.0, 50.0, 20.0, 10.0, 5.0,
        2.0, 1.0, 0.5, 0.1, 0.05, -100.0, 50.0, 40.0, 30.0, 20.0, 10.0, 5.0, 2.0, 1.0, 0.5, 0.1, 0.05, 0.01, 0.005,
        0.001, 0.0005, 0.0001, 0.00005, 0.00001, 0.000005, 0.000001, 10000.0, 5000.0, 2000.0, 1000.0, 500.0, 200.0,
        100.0, 50.0, 1000000.0, 500000.0, 200000.0, 100000.0, 50000.0, 20000.0, 10000.0, 500000.0, 20000.0, 10000.0,
        5000.0, 2000.0, 1000.0, 500.0, 20.0, 10.0, 5.0, 2.0, 1.0, 0.5, 0.1, 0.05, 0.01, 0.005, 0.001, 50000.0, 25000.0,
        10000.0, 5000.0, 2000.0, 1000.0, 500.0, 200.0, 100.0, 50.0, 20.0, 10.0, 5.0, 2.0, 1.0, 0.5, 0.1, 0.05,
    ];

    c.bench_function("npv_old", |b| {
        b.iter(|| npv_old(black_box(rate), black_box(&cash_flow)))
    });

    c.bench_function("npv", |b| b.iter(|| npv(black_box(rate), black_box(&cash_flow))));

    c.bench_function("npv_prime_r_niave", |b| {
        b.iter(|| npv_prime_r_niave(black_box(rate), black_box(&cash_flow)))
    });
    c.bench_function("npv_prime_r", |b| {
        b.iter(|| npv_prime_r(black_box(rate), black_box(&cash_flow)))
    });
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);