Coder Social home page Coder Social logo

raymon1 / financial Goto Github PK

View Code? Open in Web Editor NEW
14.0 3.0 5.0 138 KB

Financial is a Rust crate that contains collection of finance calculations memicking some of Excel Financial Functions interface.

Home Page: https://docs.rs/crate/financial

JavaScript 2.50% Rust 97.50%

financial's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

financial's Issues

xirr not working cash flow that works in Google Sheets XIRR function

I'm working on a program that calculates the money-weighted return for a given investment, and for some this series of cash flows doesn't work with the crate.

let cf = [-6.1, -13.0, 6.6];
let dates = [
        chrono::DateTime::<Utc>::from_utc(NaiveDate::from_ymd(2021,4,3).and_hms(0,0,0), Utc),
        chrono::DateTime::<Utc>::from_utc(NaiveDate::from_ymd(2021,4,21).and_hms(0,0,0), Utc),
        chrono::DateTime::<Utc>::from_utc(NaiveDate::from_ymd(2021,10,30).and_hms(0,0,0), Utc),];
println!("{}", financial::xirr(&cf, &dates, None).unwrap());

This will panic. If you provide a guess with a negative return, ie. -0.1, then the calculation will work. However, given that Google Sheet can find the XIRR without being provided a guess, there might be a deeper issue behind the calculation?

Why does it use DateTime instead of NaiveDate

Hi,

I'm curious that why this package uses DateTime with the TimeZone to be as the Cashflow Constructor.

Using NaiveDate (the Date class without HMS and TimeZone) feels much more natural to me, as Excel functions usually don't use HMS (the time part) and the TimeZone info at all.

Thanks.

irr() can produce non-optimal solutions

test case:

    #[test]
    fn irr_finds_closest_root_to_zero() {
        let cf = [10., 20., -10.];
        let guess = Some(0.);
        assert_eq!(irr(&cf, guess).unwrap(), -0.5857864377789364); // fails: returns -3.414213531256609
    }

year fraction calculation in `xnpv()`

Hi,

When converting date period into year fractions, it uses the simple algo (days between start_date and end_date) / 365.0. This actually results in slightly unexpected output when the year is a leap year (like 2020, see the example below).

I don't know if it's intended or not.

Is it open to accept other options as the year fraction calculation algo, something similar to 30/365? (See below)

I'm happy to provide a PR if it's ok.

Thanks.

Related Source Code

.map(|(v, d)| v / f64::powf(1. + rate, utils::days_to(d0.clone(), d.clone()) / 365.))

pub fn days_to<T: TimeZone>(d0: DateTime<T>, d1: DateTime<T>) -> f64 {
d1.signed_duration_since(d0).num_days() as f64
}

Example

Code

use chrono::{DateTime, NaiveDate, Utc};
use financial::*;

fn main() {
    let cf = [-100., 105.];
    let dates = [
        DateTime::<Utc>::from_utc(NaiveDate::from_ymd(2020, 1, 1).and_hms(0, 0, 0), Utc),
        DateTime::<Utc>::from_utc(NaiveDate::from_ymd(2021, 1, 1).and_hms(0, 0, 0), Utc),
    ];
    let out = xirr::<Utc>(&cf, &dates, None).unwrap();
    println!("xirr of leap year (2020) is {}", out);

    let cf = [-100., 105.];
    let dates = [
        DateTime::<Utc>::from_utc(NaiveDate::from_ymd(2021, 1, 1).and_hms(0, 0, 0), Utc),
        DateTime::<Utc>::from_utc(NaiveDate::from_ymd(2022, 1, 1).and_hms(0, 0, 0), Utc),
    ];
    let out = xirr::<Utc>(&cf, &dates, None).unwrap();
    println!("xirr of normal year(2021) is {}", out);
}

Output

I would expect both results are 0.05.

shrektan@shrektan-MBP test-rust % cargo run
   Compiling learn-rust v0.1.0 (/Users/shrektan/Documents/RWD/learn-rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.15s
     Running `target/debug/learn-rust`
xirr of leap year (2020) is 0.04986003754670357
xirr of normal year(2021) is 0.050000000000000114

Suggested algo of calculating the year fraction

pub fn year_frac(d1: &NaiveDate, d0: &NaiveDate) -> f64 {
    (d1.year() - d0.year()) as f64
    // must be as f64 first, otherwise u32 - u32 may overflow (when negative)
        + (d1.month() as f64 - d0.month() as f64) / 12.0
        + (d1.day() as f64 - d0.day() as f64) / 365.0
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.