use chrono::NaiveDate;
use crate::calendar::DayCountConvention;
use crate::cashflows::CurveProvider;
use crate::curves::Compounding;
use crate::traits::FloatExt;
#[derive(Debug, Clone)]
pub struct ZeroCouponBond<T: FloatExt> {
pub face_value: T,
pub maturity_date: NaiveDate,
}
impl<T: FloatExt> ZeroCouponBond<T> {
pub fn new(face_value: T, maturity_date: NaiveDate) -> Self {
Self {
face_value,
maturity_date,
}
}
pub fn price_from_curve(
&self,
valuation_date: NaiveDate,
discount_day_count: DayCountConvention,
curves: &(impl CurveProvider<T> + ?Sized),
) -> T {
if self.maturity_date < valuation_date {
return T::zero();
}
let tau = discount_day_count.year_fraction(valuation_date, self.maturity_date);
self.face_value * curves.discount_curve().discount_factor(tau)
}
pub fn price_from_yield(
&self,
settlement_date: NaiveDate,
yield_to_maturity: T,
yield_day_count: DayCountConvention,
compounding: Compounding,
) -> T {
if self.maturity_date < settlement_date {
return T::zero();
}
let tau = yield_day_count.year_fraction(settlement_date, self.maturity_date);
self.face_value * compounding.discount_factor(yield_to_maturity, tau)
}
pub fn yield_to_maturity(
&self,
settlement_date: NaiveDate,
price: T,
yield_day_count: DayCountConvention,
compounding: Compounding,
) -> T {
if price <= T::zero() || self.maturity_date <= settlement_date {
return T::zero();
}
let tau = yield_day_count.year_fraction(settlement_date, self.maturity_date);
let discount_factor = price / self.face_value;
compounding.zero_rate(discount_factor, tau)
}
}