use serde::{Deserialize, Serialize};
use crate::{
ad::{dual::DualFwd, scalar::Scalar},
core::{
collateral::Discountable,
instrument::{AssetClass, Instrument},
request::LegsProvider,
trade::{Side, Trade},
},
currencies::currency::Currency,
indices::marketindex::MarketIndex,
instruments::{cashflows::leg::Leg, rates::swap::Swap},
time::date::Date,
};
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum SwaptionType {
Payer,
Receiver,
}
#[derive(Clone)]
pub struct EuropeanSwaption<T: Scalar> {
identifier: String,
underlying: Swap<T>,
expiry_date: Date,
underlying_type: SwaptionType,
strike: f64,
market_index: MarketIndex,
currency: Currency,
}
impl<T> EuropeanSwaption<T>
where
T: Scalar,
{
#[must_use]
#[allow(clippy::too_many_arguments)]
pub const fn new(
identifier: String,
underlying: Swap<T>,
expiry_date: Date,
underlying_type: SwaptionType,
strike: f64,
market_index: MarketIndex,
currency: Currency,
) -> Self {
Self {
identifier,
underlying,
expiry_date,
underlying_type,
strike,
market_index,
currency,
}
}
#[must_use]
pub const fn underlying(&self) -> &Swap<T> {
&self.underlying
}
#[must_use]
pub const fn expiry_date(&self) -> Date {
self.expiry_date
}
#[must_use]
pub const fn underlying_type(&self) -> SwaptionType {
self.underlying_type
}
#[must_use]
pub const fn strike(&self) -> f64 {
self.strike
}
#[must_use]
pub fn market_index(&self) -> MarketIndex {
self.market_index.clone()
}
#[must_use]
pub const fn currency(&self) -> Currency {
self.currency
}
}
impl<T> Instrument for EuropeanSwaption<T>
where
T: Scalar,
{
fn identifier(&self) -> String {
self.identifier.clone()
}
}
impl<T> Discountable for EuropeanSwaption<T>
where
T: Scalar,
{
fn asset_class(&self) -> AssetClass {
AssetClass::InterestRate
}
fn currency(&self) -> Currency {
self.currency
}
fn discount_index(&self) -> Option<MarketIndex> {
Some(self.market_index.clone())
}
}
impl<T> LegsProvider<T> for EuropeanSwaption<T>
where
T: Scalar,
{
fn legs(&self) -> &[Leg<T>] {
self.underlying.legs()
}
}
pub struct EuropeanSwaptionTrade<T: Scalar> {
instrument: EuropeanSwaption<T>,
trade_date: Date,
notional: f64,
side: Side,
}
impl<T> EuropeanSwaptionTrade<T>
where
T: Scalar,
{
#[must_use]
pub const fn new(
instrument: EuropeanSwaption<T>,
trade_date: Date,
notional: f64,
side: Side,
) -> Self {
Self {
instrument,
trade_date,
notional,
side,
}
}
#[must_use]
pub const fn notional(&self) -> f64 {
self.notional
}
}
impl<T> Trade<EuropeanSwaption<T>> for EuropeanSwaptionTrade<T>
where
T: Scalar,
{
fn instrument(&self) -> &EuropeanSwaption<T> {
&self.instrument
}
fn trade_date(&self) -> Date {
self.trade_date
}
fn side(&self) -> Side {
self.side
}
}
impl From<EuropeanSwaption<f64>> for EuropeanSwaption<DualFwd> {
fn from(value: EuropeanSwaption<f64>) -> Self {
Self::new(
value.identifier,
value.underlying.into(),
value.expiry_date,
value.underlying_type,
value.strike,
value.market_index,
value.currency,
)
}
}
impl From<EuropeanSwaption<DualFwd>> for EuropeanSwaption<f64> {
fn from(value: EuropeanSwaption<DualFwd>) -> Self {
Self::new(
value.identifier,
value.underlying.into(),
value.expiry_date,
value.underlying_type,
value.strike,
value.market_index,
value.currency,
)
}
}
impl From<EuropeanSwaptionTrade<f64>> for EuropeanSwaptionTrade<DualFwd> {
fn from(value: EuropeanSwaptionTrade<f64>) -> Self {
Self::new(
value.instrument.into(),
value.trade_date,
value.notional,
value.side,
)
}
}
impl From<EuropeanSwaptionTrade<DualFwd>> for EuropeanSwaptionTrade<f64> {
fn from(value: EuropeanSwaptionTrade<DualFwd>) -> Self {
Self::new(
value.instrument.into(),
value.trade_date,
value.notional,
value.side,
)
}
}