use super::pricing::Greeks;
pub trait Instrument {
fn instrument_kind(&self) -> &'static str {
"Instrument"
}
}
pub trait PricingEngine<I: ?Sized> {
type Result: PricingResult;
fn calculate(&self, instrument: &I) -> Self::Result;
}
pub trait PricingResult {
fn npv(&self) -> f64;
fn greeks(&self) -> Option<Greeks> {
None
}
fn error_estimate(&self) -> Option<f64> {
None
}
}
pub trait InstrumentExt: Instrument {
fn npv<E: PricingEngine<Self>>(&self, engine: &E) -> f64
where
Self: Sized,
{
engine.calculate(self).npv()
}
fn price<E: PricingEngine<Self>>(&self, engine: &E) -> E::Result
where
Self: Sized,
{
engine.calculate(self)
}
}
impl<I: Instrument + ?Sized> InstrumentExt for I {}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct StandardResult {
pub npv: f64,
pub greeks: Option<Greeks>,
pub error_estimate: Option<f64>,
}
impl StandardResult {
pub const fn npv_only(npv: f64) -> Self {
Self {
npv,
greeks: None,
error_estimate: None,
}
}
pub const fn with_greeks(npv: f64, greeks: Greeks) -> Self {
Self {
npv,
greeks: Some(greeks),
error_estimate: None,
}
}
pub const fn mc(npv: f64, greeks: Option<Greeks>, error_estimate: f64) -> Self {
Self {
npv,
greeks,
error_estimate: Some(error_estimate),
}
}
}
impl PricingResult for StandardResult {
fn npv(&self) -> f64 {
self.npv
}
fn greeks(&self) -> Option<Greeks> {
self.greeks
}
fn error_estimate(&self) -> Option<f64> {
self.error_estimate
}
}