use crate::{
core::{
instrument::{AssetClass, Instrument},
trade::{Side, Trade},
},
currencies::currency::Currency,
time::{date::Date, daycounter::DayCounter},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FxForwardSettlement {
Deliverable,
NonDeliverable {
fixing_date: Date,
settlement_currency: Currency,
},
}
#[derive(Debug)]
pub struct FxForward {
identifier: String,
delivery_date: Date,
forward_price: Option<f64>,
forward_points: Option<f64>,
base_currency: Currency,
quote_currency: Currency,
day_counter: DayCounter,
settlement: FxForwardSettlement,
}
impl FxForward {
#[must_use]
#[allow(clippy::too_many_arguments)]
pub const fn new(
identifier: String,
delivery_date: Date,
forward_price: Option<f64>,
forward_points: Option<f64>,
base_currency: Currency,
quote_currency: Currency,
day_counter: DayCounter,
settlement: FxForwardSettlement,
) -> Self {
Self {
identifier,
delivery_date,
forward_price,
forward_points,
base_currency,
quote_currency,
day_counter,
settlement,
}
}
#[must_use]
pub const fn delivery_date(&self) -> Date {
self.delivery_date
}
#[must_use]
pub const fn forward_price(&self) -> Option<f64> {
self.forward_price
}
#[must_use]
pub const fn forward_rate(&self) -> Option<f64> {
self.forward_price
}
#[must_use]
pub const fn forward_points(&self) -> Option<f64> {
self.forward_points
}
#[must_use]
pub const fn is_outright(&self) -> bool {
self.forward_price.is_some()
}
#[must_use]
pub const fn has_forward_points(&self) -> bool {
self.forward_points.is_some()
}
#[must_use]
pub const fn settlement(&self) -> FxForwardSettlement {
self.settlement
}
#[must_use]
pub const fn is_deliverable(&self) -> bool {
match self.settlement {
FxForwardSettlement::Deliverable => true,
FxForwardSettlement::NonDeliverable { .. } => false,
}
}
#[must_use]
pub const fn is_ndf(&self) -> bool {
!self.is_deliverable()
}
#[must_use]
pub const fn fixing_date(&self) -> Option<Date> {
match self.settlement {
FxForwardSettlement::Deliverable => None,
FxForwardSettlement::NonDeliverable { fixing_date, .. } => Some(fixing_date),
}
}
#[must_use]
pub const fn settlement_currency(&self) -> Option<Currency> {
match self.settlement {
FxForwardSettlement::Deliverable => None,
FxForwardSettlement::NonDeliverable {
settlement_currency,
..
} => Some(settlement_currency),
}
}
#[must_use]
pub const fn base_currency(&self) -> Currency {
self.base_currency
}
#[must_use]
pub const fn quote_currency(&self) -> Currency {
self.quote_currency
}
#[must_use]
pub const fn day_counter(&self) -> &DayCounter {
&self.day_counter
}
}
impl Instrument for FxForward {
fn identifier(&self) -> String {
self.identifier.clone()
}
fn asset_class(&self) -> AssetClass {
AssetClass::Fx
}
}
pub struct FxForwardTrade {
instrument: FxForward,
trade_date: Date,
notional: f64,
side: Side,
}
impl FxForwardTrade {
#[must_use]
pub const fn new(instrument: FxForward, 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 Trade<FxForward> for FxForwardTrade {
fn instrument(&self) -> &FxForward {
&self.instrument
}
fn trade_date(&self) -> Date {
self.trade_date
}
fn side(&self) -> Side {
self.side
}
}