Files
IronCalc/base/src/test/test_fn_financial.rs
2023-11-20 10:46:19 +01:00

471 lines
13 KiB
Rust

#![allow(clippy::unwrap_used)]
use crate::{cell::CellValue, test::util::new_empty_model};
#[test]
fn fn_arguments() {
let mut model = new_empty_model();
model._set("A1", "=PMT()");
model._set("A2", "=PMT(1,1)");
model._set("A3", "=PMT(1,1,1,1,1,1)");
model._set("B1", "=FV()");
model._set("B2", "=FV(1,1)");
model._set("B3", "=FV(1,1,1,1,1,1)");
model._set("C1", "=PV()");
model._set("C2", "=PV(1,1)");
model._set("C3", "=PV(1,1,1,1,1,1)");
model._set("D1", "=NPER()");
model._set("D2", "=NPER(1,1)");
model._set("D3", "=NPER(1,1,1,1,1,1)");
model._set("E1", "=RATE()");
model._set("E2", "=RATE(1,1)");
model._set("E3", "=RATE(1,1,1,1,1,1)");
model.evaluate();
assert_eq!(model._get_text("A1"), *"#ERROR!");
assert_eq!(model._get_text("A2"), *"#ERROR!");
assert_eq!(model._get_text("A3"), *"#ERROR!");
assert_eq!(model._get_text("B1"), *"#ERROR!");
assert_eq!(model._get_text("B2"), *"#ERROR!");
assert_eq!(model._get_text("B3"), *"#ERROR!");
assert_eq!(model._get_text("C1"), *"#ERROR!");
assert_eq!(model._get_text("C2"), *"#ERROR!");
assert_eq!(model._get_text("C3"), *"#ERROR!");
assert_eq!(model._get_text("D1"), *"#ERROR!");
assert_eq!(model._get_text("D2"), *"#ERROR!");
assert_eq!(model._get_text("D3"), *"#ERROR!");
assert_eq!(model._get_text("E1"), *"#ERROR!");
assert_eq!(model._get_text("E2"), *"#ERROR!");
assert_eq!(model._get_text("E3"), *"#ERROR!");
}
#[test]
fn fn_impmt_ppmt_arguments() {
let mut model = new_empty_model();
model._set("A1", "=IPMT()");
model._set("A2", "=IPMT(1,1,1)");
model._set("A3", "=IPMT(1,1,1,1,1,1,1)");
model._set("B1", "=PPMT()");
model._set("B2", "=PPMT(1,1,1)");
model._set("B3", "=PPMT(1,1,1,1,1,1,1)");
model.evaluate();
assert_eq!(model._get_text("A1"), *"#ERROR!");
assert_eq!(model._get_text("A2"), *"#ERROR!");
assert_eq!(model._get_text("A3"), *"#ERROR!");
assert_eq!(model._get_text("B1"), *"#ERROR!");
assert_eq!(model._get_text("B2"), *"#ERROR!");
assert_eq!(model._get_text("B3"), *"#ERROR!");
}
#[test]
fn fn_irr_npv_arguments() {
let mut model = new_empty_model();
model._set("A1", "=NPV()");
model._set("A2", "=NPV(1,1)");
model._set("C1", "-2"); // v0
model._set("C2", "5"); // v1
model._set("B1", "=IRR()");
model._set("B3", "=IRR(1, 2, 3, 4)");
// r such that v0 + v1/(1+r) = 0
// r = -v1/v0 - 1
model._set("B4", "=IRR(C1:C2)");
model.evaluate();
assert_eq!(model._get_text("A1"), *"#ERROR!");
assert_eq!(model._get_text("A2"), *"$0.50");
assert_eq!(model._get_text("B1"), *"#ERROR!");
assert_eq!(model._get_text("B3"), *"#ERROR!");
// r = 5/2-1 = 1.5
assert_eq!(model._get_text("B4"), *"150%");
}
#[test]
fn fn_mirr() {
let mut model = new_empty_model();
model._set("A2", "-120000");
model._set("A3", "39000");
model._set("A4", "30000");
model._set("A5", "21000");
model._set("A6", "37000");
model._set("A7", "46000");
model._set("A8", "0.1");
model._set("A9", "0.12");
model._set("B1", "=MIRR(A2:A7, A8, A9)");
model._set("B2", "=MIRR(A2:A5, A8, A9)");
model.evaluate();
assert_eq!(
model.get_cell_value_by_ref("Sheet1!B1"),
Ok(CellValue::Number(0.1260941303659051))
);
assert_eq!(model._get_text("B1"), "13%");
assert_eq!(model._get_text("B2"), "-5%");
}
#[test]
fn fn_mirr_div_0() {
// This test produces #DIV/0! in Excel (but it is incorrect)
let mut model = new_empty_model();
model._set("A2", "-30");
model._set("A3", "-20");
model._set("A4", "-10");
model._set("A5", "5");
model._set("A6", "5");
model._set("A7", "5");
model._set("A8", "-1");
model._set("A9", "2");
model._set("B1", "=MIRR(A2:A7, A8, A9)");
model.evaluate();
assert_eq!(
model.get_cell_value_by_ref("Sheet1!B1"),
Ok(CellValue::Number(-1.0))
);
assert_eq!(model._get_text("B1"), "-100%");
}
#[test]
fn fn_ispmt() {
let mut model = new_empty_model();
model._set("A1", "1"); // rate
model._set("A2", "2"); // per
model._set("A3", "5"); // nper
model._set("A4", "4"); // pv
model._set("B1", "=ISPMT(A1, A2, A3, A4)");
model._set("B2", "=ISPMT(A1, A2, A3, A4, 1)");
model._set("B3", "=ISPMT(A1, A2, A3)");
model.evaluate();
assert_eq!(model._get_text("B1"), "-2.4");
assert_eq!(model._get_text("B2"), *"#ERROR!");
assert_eq!(model._get_text("B3"), *"#ERROR!");
}
#[test]
fn fn_rri() {
let mut model = new_empty_model();
model._set("A1", "1"); // nper
model._set("A2", "2"); // pv
model._set("A3", "3"); // fv
model._set("B1", "=RRI(A1, A2, A3)");
model._set("B2", "=RRI(A1, A2)");
model._set("B3", "=RRI(A1, A2, A3, 1)");
model.evaluate();
assert_eq!(model._get_text("B1"), "0.5");
assert_eq!(model._get_text("B2"), *"#ERROR!");
assert_eq!(model._get_text("B3"), *"#ERROR!");
}
#[test]
fn fn_sln() {
let mut model = new_empty_model();
model._set("A1", "1"); // cost
model._set("A2", "2"); // salvage
model._set("A3", "3"); // life
model._set("B1", "=SLN(A1, A2, A3)");
model._set("B2", "=SLN(A1, A2)");
model._set("B3", "=SLN(A1, A2, A3, 1)");
model.evaluate();
assert_eq!(
model.get_cell_value_by_ref("Sheet1!B1"),
Ok(CellValue::Number(-1.0 / 3.0))
);
assert_eq!(model._get_text("B1"), "-$0.33");
assert_eq!(model._get_text("B2"), *"#ERROR!");
assert_eq!(model._get_text("B3"), *"#ERROR!");
}
#[test]
fn fn_syd() {
let mut model = new_empty_model();
model._set("A1", "100"); // cost
model._set("A2", "5"); // salvage
model._set("A3", "20"); // life
model._set("A4", "10"); // periods
model._set("B1", "=SYD(A1, A2, A3, A4)");
model._set("B2", "=SYD(A1, A2, A3)");
model._set("B3", "=SYD(A1, A2, A3, A4, 1)");
model.evaluate();
assert_eq!(
model.get_cell_value_by_ref("Sheet1!B1"),
Ok(CellValue::Number(4.976190476190476))
);
assert_eq!(model._get_text("B1"), "$4.98");
assert_eq!(model._get_text("B2"), *"#ERROR!");
assert_eq!(model._get_text("B3"), *"#ERROR!");
}
#[test]
fn fn_effect() {
let mut model = new_empty_model();
model._set("A1", "2"); // rate
model._set("A2", "1"); // periods
model._set("B1", "=EFFECT(A1, A2)");
model._set("B2", "=EFFECT(A1)");
model._set("B3", "=EFFECT(A1, A2, A3)");
model.evaluate();
assert_eq!(model._get_text("B1"), "2");
assert_eq!(model._get_text("B2"), *"#ERROR!");
assert_eq!(model._get_text("B3"), *"#ERROR!");
}
#[test]
fn fn_nominal() {
let mut model = new_empty_model();
model._set("A1", "2"); // rate
model._set("A2", "1"); // periods
model._set("B1", "=NOMINAL(A1, A2)");
model._set("B2", "=NOMINAL(A1)");
model._set("B3", "=NOMINAL(A1, A2, A3)");
model.evaluate();
assert_eq!(model._get_text("B1"), "2");
assert_eq!(model._get_text("B2"), *"#ERROR!");
assert_eq!(model._get_text("B3"), *"#ERROR!");
}
#[test]
fn fn_db() {
let mut model = new_empty_model();
model._set("A2", "$1,000,000"); // cost
model._set("A3", "$100,000"); // salvage
model._set("A4", "6"); // life
model._set("B1", "=DB(A2,A3,A4,1,7)");
model._set("B2", "=DB(A2,A3,A4,2,7)");
model._set("B3", "=DB(A2,A3,A4,3,7)");
model._set("B4", "=DB(A2,A3,A4,4,7)");
model._set("B5", "=DB(A2,A3,A4,5,7)");
model._set("B6", "=DB(A2,A3,A4,6,7)");
model._set("B7", "=DB(A2,A3,A4,7,7)");
model._set("C1", "=DB(A2,A3,A4,7,7,1)");
model._set("C2", "=DB(A2,A3,A4)");
model.evaluate();
assert_eq!(model._get_text("B1"), "$186,083.33");
assert_eq!(model._get_text("B2"), "$259,639.42");
assert_eq!(model._get_text("B3"), "$176,814.44");
assert_eq!(model._get_text("B4"), "$120,410.64");
assert_eq!(model._get_text("B5"), "$81,999.64");
assert_eq!(model._get_text("B6"), "$55,841.76");
assert_eq!(model._get_text("B7"), "$15,845.10");
assert_eq!(model._get_text("C1"), *"#ERROR!");
assert_eq!(model._get_text("C2"), *"#ERROR!");
}
#[test]
fn fn_ddb() {
let mut model = new_empty_model();
model._set("A2", "$2,400"); // cost
model._set("A3", "$300"); // salvage
model._set("A4", "10"); // life
model._set("B1", "=DDB(A2,A3,A4*365,1)");
model._set("B2", "=DDB(A2,A3,A4*12,1,2)");
model._set("B3", "=DDB(A2,A3,A4,1,2)");
model._set("B4", "=DDB(A2,A3,A4,2,1.5)");
model._set("B5", "=DDB(A2,A3,A4,10)");
model._set("C1", "=DB(A2,A3,A4,7,7,1)");
model._set("C2", "=DB(A2,A3,A4)");
model.evaluate();
assert_eq!(model._get_text("B1"), "$1.32");
assert_eq!(model._get_text("B2"), "$40.00");
assert_eq!(model._get_text("B3"), "$480.00");
assert_eq!(model._get_text("B4"), "$306.00");
assert_eq!(model._get_text("B5"), "$22.12");
assert_eq!(model._get_text("C1"), *"#ERROR!");
assert_eq!(model._get_text("C2"), *"#ERROR!");
}
#[test]
fn fn_tbilleq() {
let mut model = new_empty_model();
model._set("A2", "=DATE(2008, 3, 31)"); // settlement date
model._set("A3", "=DATE(2008, 6, 1)"); // maturity date
model._set("A4", "9.14%");
model._set("B1", "=TBILLEQ(A2,A3,A4)");
model._set("C1", "=TBILLEQ(A2,A3)");
model._set("C2", "=TBILLEQ(A2,A3,A4,1)");
model.evaluate();
assert_eq!(model._get_text("B1"), "9.42%");
assert_eq!(model._get_text("C1"), *"#ERROR!");
assert_eq!(model._get_text("C2"), *"#ERROR!");
}
#[test]
fn fn_tbillprice() {
let mut model = new_empty_model();
model._set("A2", "=DATE(2008, 3, 31)"); // settlement date
model._set("A3", "=DATE(2008, 6, 1)"); // maturity date
model._set("A4", "9.0%");
model._set("B1", "=TBILLPRICE(A2,A3,A4)");
model._set("C1", "=TBILLPRICE(A2,A3)");
model._set("C2", "=TBILLPRICE(A2,A3,A4,1)");
model.evaluate();
assert_eq!(model._get_text("B1"), "$98.45");
assert_eq!(model._get_text("C1"), *"#ERROR!");
assert_eq!(model._get_text("C2"), *"#ERROR!");
}
#[test]
fn fn_tbillyield() {
let mut model = new_empty_model();
model._set("A2", "=DATE(2008, 3, 31)"); // settlement date
model._set("A3", "=DATE(2008, 6, 1)"); // maturity date
model._set("A4", "$98.45");
model._set("B1", "=TBILLYIELD(A2,A3,A4)");
model._set("C1", "=TBILLYIELD(A2,A3)");
model._set("C2", "=TBILLYIELD(A2,A3,A4,1)");
model.evaluate();
assert_eq!(model._get_text("B1"), "9.14%");
assert_eq!(model._get_text("C1"), *"#ERROR!");
assert_eq!(model._get_text("C2"), *"#ERROR!");
}
#[test]
fn fn_dollarde() {
let mut model = new_empty_model();
model._set("A1", "=DOLLARDE(1.02, 16)");
model._set("A2", "=DOLLARDE(1.1, 32)");
model._set("C1", "=DOLLARDE(1.1)");
model._set("C2", "=DOLLARDE(1.1, 32, 1)");
model.evaluate();
assert_eq!(model._get_text("A1"), "1.125");
assert_eq!(model._get_text("A2"), "1.3125");
assert_eq!(model._get_text("C1"), *"#ERROR!");
assert_eq!(model._get_text("C2"), *"#ERROR!");
}
#[test]
fn fn_dollarfr() {
let mut model = new_empty_model();
model._set("A1", "=DOLLARFR(1.125,16)");
model._set("A2", "=DOLLARFR(1.125,32)");
model._set("C1", "=DOLLARFR(1.1)");
model._set("C2", "=DOLLARFR(1.1, 32, 1)");
model.evaluate();
assert_eq!(model._get_text("A1"), "1.02");
assert_eq!(model._get_text("A2"), "1.04");
assert_eq!(model._get_text("C1"), *"#ERROR!");
assert_eq!(model._get_text("C2"), *"#ERROR!");
}
#[test]
fn fn_cumipmt() {
let mut model = new_empty_model();
model._set("A2", "9%"); // annual interest rate
model._set("A3", "30"); // years of the load
model._set("A4", "$125,000"); // present value
model._set("B1", "=CUMIPMT(A2/12,A3*12,A4,13,24,0)");
model._set("B2", "=CUMIPMT(A2/12,A3*12,A4,1,1,0)");
model._set("C1", "=CUMIPMT(A2/12,A3*12,A4,1,1,0,1)");
model._set("C2", "=CUMIPMT(A2/12,A3*12,A4,1,1)");
model.evaluate();
assert_eq!(model._get_text("B1"), "-$11,135.23");
assert_eq!(model._get_text("B2"), "-$937.50");
assert_eq!(model._get_text("C1"), *"#ERROR!");
assert_eq!(model._get_text("C2"), *"#ERROR!");
}
#[test]
fn fn_cumprinc() {
let mut model = new_empty_model();
model._set("A2", "9%"); // annual interest rate
model._set("A3", "30"); // years of the load
model._set("A4", "$125,000"); // present value
model._set("B1", "=CUMPRINC(A2/12,A3*12,A4,13,24,0)");
model._set("B2", "=CUMPRINC(A2/12,A3*12,A4,1,1,0)");
model._set("C1", "=CUMPRINC(A2/12,A3*12,A4,1,1,0,1)");
model._set("C2", "=CUMPRINC(A2/12,A3*12,A4,1,1)");
model.evaluate();
assert_eq!(model._get_text("B1"), "-$934.11");
assert_eq!(model._get_text("B2"), "-$68.28");
assert_eq!(model._get_text("C1"), *"#ERROR!");
assert_eq!(model._get_text("C2"), *"#ERROR!");
}
#[test]
fn fn_db_misc() {
let mut model = new_empty_model();
model._set("B1", "=DB(0,10,1,2,2)");
model.evaluate();
assert_eq!(model._get_text("B1"), "$0.00");
}