use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
use super::curves::PyDiscountCurve;
use crate::traits::PricerExt;
#[pyclass(name = "VasicekBond", unsendable)]
pub struct PyVasicekBond {
inner: crate::bonds::vasicek::Vasicek,
}
#[pymethods]
impl PyVasicekBond {
#[new]
fn new(r_t: f64, theta: f64, mu: f64, sigma: f64, tau: f64) -> Self {
Self {
inner: crate::bonds::vasicek::Vasicek {
r_t,
theta,
mu,
sigma,
tau,
eval: None,
expiration: None,
},
}
}
fn price(&self) -> f64 {
self.inner.calculate_price()
}
}
#[pyclass(name = "CIRBond", unsendable)]
pub struct PyCIRBond {
inner: crate::bonds::cir::Cir,
}
#[pymethods]
impl PyCIRBond {
#[new]
fn new(r_t: f64, theta: f64, mu: f64, sigma: f64, tau: f64) -> Self {
Self {
inner: crate::bonds::cir::Cir {
r_t,
theta,
mu,
sigma,
tau,
eval: None,
expiration: None,
},
}
}
fn price(&self) -> f64 {
self.inner.calculate_price()
}
}
#[pyclass(name = "HullWhiteBond", unsendable)]
pub struct PyHullWhiteBond {
inner: crate::bonds::hull_white::HullWhite,
}
#[pymethods]
impl PyHullWhiteBond {
#[new]
#[allow(clippy::too_many_arguments)]
#[pyo3(signature = (r_t, alpha, sigma, t, tau, p0_at_t, p0_at_maturity, f0_at_t))]
fn new(
r_t: f64,
alpha: f64,
sigma: f64,
t: f64,
tau: f64,
p0_at_t: f64,
p0_at_maturity: f64,
f0_at_t: f64,
) -> PyResult<Self> {
if alpha <= 0.0 || sigma <= 0.0 {
return Err(PyValueError::new_err("alpha and sigma must be > 0"));
}
if tau < 0.0 {
return Err(PyValueError::new_err("tau must be >= 0"));
}
Ok(Self {
inner: crate::bonds::hull_white::HullWhite {
r_t,
alpha,
sigma,
tau,
t,
p0_at_t,
p0_at_maturity,
f0_at_t,
eval: None,
expiration: None,
},
})
}
#[staticmethod]
#[pyo3(signature = (curve, r_t, alpha, sigma, t, tau))]
fn from_curve(
curve: &PyDiscountCurve,
r_t: f64,
alpha: f64,
sigma: f64,
t: f64,
tau: f64,
) -> PyResult<Self> {
if alpha <= 0.0 || sigma <= 0.0 {
return Err(PyValueError::new_err("alpha and sigma must be > 0"));
}
if tau < 0.0 {
return Err(PyValueError::new_err("tau must be >= 0"));
}
Ok(Self {
inner: crate::bonds::hull_white::HullWhite::from_curve(
&curve.inner,
r_t,
alpha,
sigma,
t,
tau,
None,
None,
),
})
}
fn price(&self) -> f64 {
self.inner.calculate_price()
}
}