use crate::{
ad::scalar::Scalar,
core::{instrument::AssetClass, trade::Side},
currencies::currency::Currency,
indices::marketindex::MarketIndex,
instruments::{
cashflows::makeleg::{MakeLeg, RateType},
fixedincome::fixedratedeposit::FixedRateDeposit,
},
rates::interestrate::{InterestRate, RateDefinition},
time::{date::Date, enums::Frequency},
utils::errors::{QSError, Result},
};
use std::marker::PhantomData;
#[derive(Default)]
pub struct MakeFixedRateDeposit<T: Scalar> {
start_date: Option<Date>,
maturity_date: Option<Date>,
rate: Option<f64>,
units: Option<f64>,
notional: Option<f64>,
identifier: Option<String>,
rate_definition: Option<RateDefinition>,
discount_index: Option<MarketIndex>,
currency: Option<Currency>,
side: Option<Side>,
_marker: PhantomData<T>,
}
impl<T> MakeFixedRateDeposit<T>
where
T: Scalar,
{
#[must_use]
pub const fn with_start_date(mut self, start_date: Date) -> Self {
self.start_date = Some(start_date);
self
}
#[must_use]
pub const fn with_maturity_date(mut self, maturity_date: Date) -> Self {
self.maturity_date = Some(maturity_date);
self
}
#[must_use]
pub const fn with_rate(mut self, rate: f64) -> Self {
self.rate = Some(rate);
self
}
#[must_use]
pub const fn with_notional(mut self, notional: f64) -> Self {
self.notional = Some(notional);
self
}
#[must_use]
pub const fn with_rate_definition(mut self, rate_definition: RateDefinition) -> Self {
self.rate_definition = Some(rate_definition);
self
}
#[must_use]
pub fn with_discount_index(mut self, discount_index: Option<MarketIndex>) -> Self {
self.discount_index = discount_index;
self
}
#[must_use]
pub const fn with_currency(mut self, currency: Currency) -> Self {
self.currency = Some(currency);
self
}
#[must_use]
pub const fn with_units(mut self, units: f64) -> Self {
self.units = Some(units);
self
}
#[must_use]
pub fn with_identifier(mut self, identifier: String) -> Self {
self.identifier = Some(identifier);
self
}
#[must_use]
pub const fn with_side(mut self, side: Side) -> Self {
self.side = Some(side);
self
}
pub fn build(self) -> Result<FixedRateDeposit<T>> {
let notional = self
.notional
.ok_or_else(|| QSError::ValueNotSetErr("Notional".into()))?;
let start_date = self
.start_date
.ok_or_else(|| QSError::ValueNotSetErr("Start date".into()))?;
let maturity_date = self
.maturity_date
.ok_or_else(|| QSError::ValueNotSetErr("Maturity date".into()))?;
let rate = self
.rate
.ok_or_else(|| QSError::ValueNotSetErr("Rate".into()))?;
let rate_definition = self
.rate_definition
.ok_or_else(|| QSError::ValueNotSetErr("Rate definition".into()))?;
let currency = self
.currency
.ok_or_else(|| QSError::ValueNotSetErr("Currency".into()))?;
let identifier = self
.identifier
.ok_or_else(|| QSError::ValueNotSetErr("Identifier".into()))?;
let units = self.units.unwrap_or(100.0);
let side = self.side.unwrap_or(Side::LongReceive);
let interest_rate = InterestRate::from_rate_definition(T::scalar(rate), rate_definition);
let leg = MakeLeg::<T>::default()
.with_leg_id(0)
.with_notional(notional)
.with_side(side)
.with_asset_class(AssetClass::FixedIncome)
.with_currency(currency)
.with_discount_index(self.discount_index.clone())
.with_start_date(start_date)
.with_end_date(maturity_date)
.with_rate_type(RateType::Fixed)
.with_rate(interest_rate)
.with_payment_frequency(Frequency::Once)
.bullet()
.build()?;
Ok(FixedRateDeposit::new(
identifier,
units,
leg,
self.discount_index,
start_date,
maturity_date,
currency,
))
}
}