libitofin 0.33.0

A ground-up Rust port of QuantLib: quantitative-finance primitives for pricing, risk, and numerical methods.
Documentation
use super::*;

#[test]
fn paths_match_independent_mt_inverse_normal_compound_poisson_fixtures() {
    let cases: [(MertonRequest, &[Real]); 6] = [
        (
            MertonRequest { ..request() },
            &[
                100.0,
                55.496279986665456,
                61.56714406017473,
                73.98365027969385,
                69.02629897681246,
                100.0,
                108.62856072310466,
                119.8125070496225,
                111.58288619351339,
                116.76538287683597,
                100.0,
                92.29161151619682,
                154.0450892411835,
                142.169262692087,
                127.70559854247949,
            ],
        ),
        (
            MertonRequest {
                jump_intensity: 8.0,
                ..request()
            },
            &[
                100.0,
                28.00041450333543,
                26.378803084925767,
                28.4339161265367,
                22.752796237247246,
                100.0,
                119.29332236764716,
                144.49285526648308,
                107.6294091848049,
                51.95116780562126,
                100.0,
                126.107229774437,
                294.7096444500288,
                256.4689457575154,
                286.139272112366,
            ],
        ),
        (
            MertonRequest {
                jump_intensity: 3.0,
                log_mean_jump: 0.08,
                ..request()
            },
            &[
                100.0,
                52.730096030553106,
                52.2353089695446,
                75.69290879235727,
                63.060077181577874,
                100.0,
                96.99838318766764,
                95.53072982707711,
                102.30871162211999,
                74.6299781910955,
                100.0,
                120.43204744873255,
                299.0918211843931,
                246.4806667545246,
                197.70040356791543,
            ],
        ),
        (
            MertonRequest {
                jump_intensity: 8.0,
                log_jump_volatility: 0.0,
                ..request()
            },
            &[
                100.0,
                79.12351485783925,
                85.77854551855636,
                82.66332429758566,
                83.29311774545027,
                100.0,
                129.6554845624747,
                170.68520977207467,
                142.96985064552015,
                132.28771142198252,
                100.0,
                81.60574839290943,
                72.68282889871548,
                72.44477938826813,
                70.2795122968073,
            ],
        ),
        (
            MertonRequest {
                jump_intensity: 0.0,
                ..request()
            },
            &[
                100.0,
                97.5812092582015,
                106.81716078633639,
                126.95091719935475,
                116.87035809017503,
                100.0,
                107.1849288852535,
                116.6491432268552,
                120.50102770905656,
                124.42193945169578,
                100.0,
                91.06509145679009,
                90.50950181010404,
                82.42173004218758,
                73.05259550932476,
            ],
        ),
        (
            MertonRequest {
                jump_intensity: 8.0,
                volatility: 0.0,
                ..request()
            },
            &[
                100.0,
                29.055405826404364,
                25.32044988390155,
                23.25342226573439,
                20.46657290764477,
                100.0,
                112.6966719094299,
                127.00539859461685,
                92.73127871099057,
                43.894799725600876,
                100.0,
                140.22218767953282,
                333.8547319075621,
                323.05696110490584,
                411.7717436492832,
            ],
        ),
    ];
    for (r, expected) in cases {
        assert_fixture(&r, expected);
    }
}

#[test]
fn stream_words_transforms_and_jump_counts_match_independent_fixture() {
    let expected = [
        (-0.31985239197154675, 1.0, -1.5924922285463126),
        (0.8293364834726858, 0.0, -0.13463759062854916),
        (1.6518193787298954, 1.0, 0.3255170771478866),
        (-0.9023526306658766, 0.0, -0.4906301803491114),
        (0.6188546400812096, 0.0, -0.044280788413889466),
        (0.7711500362518082, 0.0, 0.6917808538610539),
        (0.24987627978810856, 1.0, -0.056755773225366166),
        (0.24520245306794447, 0.0, -1.0920381783960909),
        (-1.0109564443577614, 0.0, 0.9979082350921727),
        (-0.13619703980908432, 1.0, 2.016776944151818),
        (-1.0110572131821498, 0.0, -0.17469003401683866),
        (-1.2816944810144082, 0.0, 0.7437027120568257),
    ];
    let mut draws = Draws::new(42, 0.25).unwrap();
    for (zd, count, zj) in expected {
        let (actual_zd, actual_count, actual_zj) = draws.next().unwrap();
        assert_close(actual_zd, zd, 2e-14);
        assert_eq!(actual_count, count);
        assert_close(actual_zj, zj, 2e-14);
    }
    let words = [
        [1608637542, 3915449494, 238959412],
        [3421126067, 1922758419, 1917484754],
        [4083286876, 3793001662, 2695543465],
        [787846414, 1292008319, 1339359860],
        [3143890026, 497193590, 2071635782],
        [3348747335, 422964674, 3244686812],
        [2571218620, 3859116204, 2050287990],
        [2563451924, 3340158409, 590163555],
        [670094950, 3196662619, 3611372014],
        [1914837113, 3626724470, 4201081896],
        [669991378, 903544153, 1849677485],
        [429389014, 678563324, 3313446262],
    ];
    let mut diffusion = MersenneTwisterUniformRng::new(42);
    let mut poisson = MersenneTwisterUniformRng::new(2654435811);
    let mut jump = MersenneTwisterUniformRng::new(3144134319);
    for expected in words {
        assert_eq!(
            [diffusion.next_u32(), poisson.next_u32(), jump.next_u32()],
            expected
        );
    }
}