#monte-carlo #quant #racing #simulation #finish #model #events

bentobox

赛车事件中快速、无分配的蒙特卡洛模型,模拟前N名领奖台完成情况

2个版本

0.1.1 2023年10月11日
0.1.0 2023年10月11日

#1452算法

MIT 许可证

14KB
276

bentobox

bentobox是一个赛车事件中快速、无分配的前N名领奖台蒙特卡洛模型。仅根据获胜概率推导出任意位置的概率。还推导出多个选手的联合概率,这些选手具有任意(精确和前N名)排名。

性能

使用tinyrand RNG在14名选手的前4名领奖台上进行大约20M次模拟/秒。大约80%的时间用于RNG例程。

示例

来源于examples/multi.rs

use bentobox::mc;
use bentobox::probs::SliceExt;
use bentobox::selection::Selection;
use tinyrand::StdRand;
use bentobox::capture::{CaptureMut, Capture};

// probs taken from a popular website
let mut probs = vec![
    1.0 / 11.0,
    1.0 / 41.0,
    1.0 / 18.0,
    1.0 / 12.0,
    1.0 / 91.0,
    1.0 / 101.0,
    1.0 / 4.8,
    1.0 / 14.0,
    1.0 / 2.9,
    1.0 / 91.0,
    1.0 / 9.0,
    1.0 / 91.0,
    1.0 / 5.0,
    1.0 / 21.0,
];

// force probs to sum to 1 and extract the approximate overround used (multiplicative method assumed)
let overround = probs.normalize();

println!("fair probs: {probs:?}");
println!("overround: {overround:.3}");

// create an MC engine for reuse
let mut engine = mc::MonteCarloEngine::default()
    .with_iterations(10_000)
    .with_probabilities(Capture::Borrowed(&probs))
    .with_podium_places(4)
    .with_rand(CaptureMut::Owned(StdRand::default()));

// simulate top-N rankings for all runners
// NOTE: rankings and runner numbers are zero-based
for runner in 0..probs.len() {
    println!("runner: {runner}");
    for rank in 0..4 {
        let frac = engine.simulate(&vec![Selection::Top { runner, rank }]);
        println!(
            "    rank: 0~{rank}, prob: {}, fair price: {:.3}, market odds: {:.3}",
            frac.quotient(),
            1.0 / frac.quotient(),
            1.0 / frac.quotient() / overround
        );
    }
}

// simulate a same-race multi for a chosen selection vector
let selections = vec![
    Selection::Top { runner: 0, rank: 0 },
    Selection::Top { runner: 1, rank: 1 },
    Selection::Top { runner: 2, rank: 2 },
];
let frac = engine.simulate(&selections);
println!(
    "probability of {selections:?}: {}, fair price: {:.3}, market odds: {:.3}",
    frac.quotient(),
    1.0 / frac.quotient(),
    1.0 / frac.quotient() / overround
);

依赖项

~66KB