use rand::{rngs::StdRng, Rng, SeedableRng};
use std::f64::consts::PI;
#[derive(Clone, Debug)]
pub enum ModelParameters {
Gbm(GbmModelParameters),
HullWhite,
}
#[derive(Clone, Copy, Debug)]
pub struct GbmModelParameters {
n_paths: usize,
seed: u64,
}
impl Default for GbmModelParameters {
fn default() -> Self {
Self {
n_paths: 10_000,
seed: 0,
}
}
}
impl GbmModelParameters {
#[must_use]
pub const fn new(n_paths: usize, seed: u64) -> Self {
Self { n_paths, seed }
}
#[must_use]
pub const fn n_paths(&self) -> usize {
self.n_paths
}
#[must_use]
pub const fn seed(&self) -> u64 {
self.seed
}
#[must_use]
pub fn generate_draws(&self) -> Vec<f64> {
let mut rng = StdRng::seed_from_u64(self.seed);
let mut draws = Vec::with_capacity(self.n_paths);
while draws.len() < self.n_paths {
let u1: f64 = rng.gen::<f64>().max(f64::EPSILON);
let u2: f64 = rng.gen::<f64>();
let r = (-2.0 * u1.ln()).sqrt();
let theta = 2.0 * PI * u2;
draws.push(r * theta.cos());
if draws.len() < self.n_paths {
draws.push(r * theta.sin());
}
}
draws
}
}