atelier_quant 0.0.12

Quantitative Finance Tools & Models for the atelier-rs engine
Documentation
//! # Homogeneous Poisson process
//!
//! A Poisson process is a memoryless point process with constant intensity
//! λ(t) = λ.  Interarrival times are i.i.d. Exp(λ).
//!
//! This serves as the natural null-hypothesis baseline when benchmarking
//! self-exciting models such as Hawkes.

use rand::Rng;

use super::errors::PoissonError;

/// Homogeneous Poisson process with constant rate λ.
pub struct PoissonProcess {
    /// Constant intensity (events per time unit).
    pub lambda: f64,
}

impl PoissonProcess {
    /// Create a new `PoissonProcess` with the given rate.
    ///
    /// # Errors
    ///
    /// Returns [`PoissonError::InvalidRate`] if `lambda` is not finite,
    /// NaN, or ≤ 0.
    pub fn new(lambda: f64) -> Result<Self, PoissonError> {
        if !lambda.is_finite() || lambda <= 0.0 {
            return Err(PoissonError::InvalidRate(lambda));
        }
        Ok(Self { lambda })
    }

    /// Return the intensity at any time.
    ///
    /// For a homogeneous Poisson process this is always λ, regardless of
    /// the time or event history (memoryless property).
    #[inline]
    pub fn lambda(&self, _t: f64, _event_times: &[f64]) -> f64 {
        self.lambda
    }

    /// Simulate `n` event times starting after `current_ts`.
    ///
    /// Interarrivals are sampled as Exp(λ) via the inverse-CDF method:
    /// Δt = −ln(U) / λ,  U ~ Uniform(0,1).
    ///
    /// Returns a `Vec<f64>` of exactly `n` strictly increasing event times.
    ///
    /// # Arguments
    ///
    /// * `current_ts` - Start time for simulation (first event is after this).
    /// * `n` - Number of events to generate.
    pub fn generate_values(&self, current_ts: f64, n: usize) -> Vec<f64> {
        let mut rng = rand::rng();
        let mut events = Vec::with_capacity(n);
        let mut t = current_ts;

        for _ in 0..n {
            let u: f64 = rng.random();
            let wait = -u.ln() / self.lambda;
            t += wait;
            events.push(t);
        }

        events
    }
}