use crate::bonds::*;
pub struct CoxIngersollRoss {
a: f64,
b: f64,
sigma: f64,
r: f64,
t: f64,
maturity: f64,
}
impl ZeroCouponBond for CoxIngersollRoss {
fn price(&self) -> f64 {
let a = self.a;
let b = self.b;
let sigma = self.sigma;
let r = self.r;
let t = self.t;
let maturity = self.maturity;
let tau = maturity - t;
let gamma = (a * a + 2_f64 * sigma.powi(2)).sqrt();
let b_t = 2_f64 * ((gamma * tau).exp() - 1_f64)
/ ((gamma + a) * ((gamma * tau).exp() - 1_f64) + 2_f64 * gamma);
let a_t = (2_f64 * gamma * ((a + gamma) * tau / 2_f64).exp()
/ ((gamma + a) * ((gamma * tau).exp() - 1_f64) + 2_f64 * gamma))
.powf(2_f64 * a * b / sigma.powi(2));
a_t * (-b_t * r).exp()
}
}
#[cfg(test)]
mod tests {
use crate::assert_approx_equal;
use super::*;
#[test]
fn test_cir_zero_coupon_bond() {
let cir = CoxIngersollRoss {
a: 0.3,
b: 0.1,
sigma: 0.03,
r: 0.03,
t: 0.0,
maturity: 1.0,
};
let cir_price = cir.price();
assert_approx_equal!(cir_price, 0.96125071, 1e-8);
}
}