use std::collections::HashSet;
use crate::{
ad::adreal::ADReal,
core::request::LegsProvider,
currencies::currency::Currency,
indices::marketindex::MarketIndex,
math::interpolation::interpolator::Interpolator,
quotes::quote::{BuiltInstrument, Level, Quote},
rates::bootstrapping::bootstrapdiscountpolicy::BootstrapDiscountPolicy,
time::{date::Date, daycounter::DayCounter},
};
pub struct ResolvedInstrument {
quote: Quote,
level: Level,
built: BuiltInstrument,
quote_value: ADReal,
pillar_date: Date,
}
impl ResolvedInstrument {
#[must_use]
pub const fn new(
quote: Quote,
level: Level,
built: BuiltInstrument,
quote_value: ADReal,
pillar_date: Date,
) -> Self {
Self {
quote,
level,
built,
quote_value,
pillar_date,
}
}
#[must_use]
pub const fn quote(&self) -> &Quote {
&self.quote
}
#[must_use]
pub const fn level(&self) -> Level {
self.level
}
#[must_use]
pub const fn built(&self) -> &BuiltInstrument {
&self.built
}
#[must_use]
pub const fn quote_value(&self) -> &ADReal {
&self.quote_value
}
#[must_use]
pub const fn pillar_date(&self) -> Date {
self.pillar_date
}
#[must_use]
pub fn pillar_label(&self) -> String {
self.quote.details().identifier()
}
}
pub struct ResolvedCurveSpec {
market_index: MarketIndex,
currency: Currency,
day_counter: DayCounter,
interpolator: Interpolator,
enable_extrapolation: bool,
reference_date: Date,
instruments: Vec<ResolvedInstrument>,
}
impl ResolvedCurveSpec {
#[must_use]
pub const fn new(
market_index: MarketIndex,
currency: Currency,
day_counter: DayCounter,
interpolator: Interpolator,
enable_extrapolation: bool,
reference_date: Date,
instruments: Vec<ResolvedInstrument>,
) -> Self {
Self {
market_index,
currency,
day_counter,
interpolator,
enable_extrapolation,
reference_date,
instruments,
}
}
#[must_use]
pub const fn reference_date(&self) -> Date {
self.reference_date
}
#[must_use]
pub const fn market_index(&self) -> &MarketIndex {
&self.market_index
}
#[must_use]
pub const fn currency(&self) -> Currency {
self.currency
}
#[must_use]
pub const fn day_counter(&self) -> DayCounter {
self.day_counter
}
#[must_use]
pub const fn interpolator(&self) -> Interpolator {
self.interpolator
}
#[must_use]
pub const fn enable_extrapolation(&self) -> bool {
self.enable_extrapolation
}
#[must_use]
pub fn instruments(&self) -> &[ResolvedInstrument] {
&self.instruments
}
#[must_use]
pub fn dependencies(&self, policy: &BootstrapDiscountPolicy) -> HashSet<MarketIndex> {
let target = &self.market_index;
let mut deps = HashSet::new();
for instr in &self.instruments {
for dep in policy.dependencies(instr.built(), target) {
deps.insert(dep);
}
match instr.built() {
BuiltInstrument::Swap(s) => {
for leg in s.legs() {
if let Some(idx) = leg.market_index() {
if idx != target {
deps.insert(idx.clone());
}
}
}
}
BuiltInstrument::BasisSwap(bs) => {
for leg in bs.legs() {
if let Some(idx) = leg.market_index() {
if idx != target {
deps.insert(idx.clone());
}
}
}
}
BuiltInstrument::CrossCurrencySwap(xccy) => {
for leg in xccy.legs() {
if let Some(idx) = leg.market_index() {
if idx != target {
deps.insert(idx.clone());
}
}
}
}
_ => {}
}
}
deps
}
#[must_use]
pub fn pillar_dates(&self) -> Vec<Date> {
self.instruments
.iter()
.map(ResolvedInstrument::pillar_date)
.collect()
}
#[must_use]
pub fn pillar_labels(&self) -> Vec<String> {
self.instruments
.iter()
.map(ResolvedInstrument::pillar_label)
.collect()
}
#[must_use]
pub fn quote_values(&self) -> Vec<ADReal> {
self.instruments.iter().map(|i| *i.quote_value()).collect()
}
}