pub mod marketdata;
pub mod dependencies;
pub mod cache;
pub mod bumptime;
pub mod deltagamma;
pub mod timebumped;
pub mod vegavolga;
use risk::timebumped::{TimeBumpedReportGenerator, TimeBumpedReport};
use risk::deltagamma::{DeltaGammaReportGenerator, DeltaGammaReport};
use risk::vegavolga::{VegaVolgaReportGenerator, VegaVolgaReport};
use core::qm;
use core::factories::{Qrc, Qbox, TypeId, Registry};
use data::bump::Bump;
use risk::bumptime::BumpTime;
use risk::marketdata::MarketData;
use instruments::PricingContext;
use risk::dependencies::DependencyCollector;
use erased_serde as esd;
use serde as sd;
use serde_tagged as sdt;
use serde_tagged::de::BoxFnSeed;
use std::fmt::Debug;
use std::any::Any;
use std::fmt;
use std::ops::Deref;
use math::numerics::ApproxEq;
pub trait Bumpable {
fn bump(&mut self, bump: &Bump, save: Option<&mut Saveable>)
-> Result<bool, qm::Error>;
fn dependencies(&self) -> Result<&DependencyCollector, qm::Error>;
fn context(&self) -> &PricingContext;
fn new_saveable(&self) -> Box<Saveable>;
fn restore(&mut self, saved: &Saveable) -> Result<(), qm::Error>;
}
pub trait BumpablePricingContext: Bumpable + PricingContext + BumpablePricingContextClone {
fn as_bumpable(&self) -> &Bumpable;
fn as_mut_bumpable(&mut self) -> &mut Bumpable;
fn as_pricing_context(&self) -> &PricingContext;
fn raw_market_data(&self) -> &MarketData;
}
pub trait BumpablePricingContextClone {
fn clone_box(&self) -> Box<BumpablePricingContext>;
}
impl<T> BumpablePricingContextClone for T
where T: 'static + BumpablePricingContext + Clone,
{
fn clone_box(&self) -> Box<BumpablePricingContext> {
Box::new(self.clone())
}
}
impl Clone for Box<BumpablePricingContext> {
fn clone(&self) -> Box<BumpablePricingContext> {
self.clone_box()
}
}
pub trait TimeBumpable {
fn bump_time(&mut self, bump: &BumpTime) -> Result<(), qm::Error>;
}
pub trait Pricer : Bumpable + TimeBumpable + PricerClone {
fn as_bumpable(&self) -> &Bumpable;
fn as_mut_bumpable(&mut self) -> &mut Bumpable;
fn as_mut_time_bumpable(&mut self) -> &mut TimeBumpable;
fn price(&self ) -> Result<f64, qm::Error>;
}
pub trait PricerClone {
fn clone_box(&self) -> Box<Pricer>;
}
pub trait Saveable : Any {
fn as_any(&self) -> &Any;
fn as_mut_any(&mut self) -> &mut Any;
fn clear(&mut self);
}
pub trait Report : esd::Serialize + ApproxEqReport + TypeId + Debug + Any {
fn as_any(&self) -> &Any;
}
pub trait ApproxEqReport {
fn validate_report(&self, other: &Report, tol: &ReportTolerances,
msg: &str, diffs: &mut fmt::Formatter) -> fmt::Result;
}
pub struct ReportTolerances {
price: f64,
currency_risk: f64,
unit_risk: f64
}
impl ReportTolerances {
pub fn new(price: f64, currency_risk: f64, unit_risk: f64) -> ReportTolerances {
ReportTolerances { price, currency_risk, unit_risk }
}
pub fn price(&self) -> f64 { self.price }
pub fn currency_risk(&self) -> f64 { self.currency_risk }
pub fn unit_risk(&self) -> f64 { self.unit_risk }
}
pub trait ReportGenerator : esd::Serialize + TypeId + Sync + Send + Debug {
fn generate(&self, pricer: &mut Pricer, saveable: &mut Saveable, unbumped: f64)
-> Result<BoxReport, qm::Error>;
}
pub type RcReportGenerator = Qrc<ReportGenerator>;
pub type GeneratorTypeRegistry = Registry<BoxFnSeed<Qrc<ReportGenerator>>>;
impl<'de> sd::Deserialize<'de> for Qrc<ReportGenerator> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: sd::Deserializer<'de>
{
sdt::de::external::deserialize(deserializer, get_generator_registry())
}
}
pub fn get_generator_registry() -> &'static GeneratorTypeRegistry {
lazy_static! {
static ref REG: GeneratorTypeRegistry = {
let mut reg = GeneratorTypeRegistry::new();
reg.insert("DeltaGammaReportGenerator", BoxFnSeed::new(DeltaGammaReportGenerator::from_serial));
reg.insert("VegaVolgaReportGenerator", BoxFnSeed::new(VegaVolgaReportGenerator::from_serial));
reg.insert("TimeBumpedReportGenerator", BoxFnSeed::new(TimeBumpedReportGenerator::from_serial));
reg
};
}
®
}
pub type BoxReport = Qbox<Report>;
pub type ReportTypeRegistry = Registry<BoxFnSeed<BoxReport>>;
impl<'de> sd::Deserialize<'de> for BoxReport {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: sd::Deserializer<'de>
{
sdt::de::external::deserialize(deserializer, get_report_registry())
}
}
impl<'v> ApproxEq<ReportTolerances, &'v BoxReport> for &'v BoxReport {
fn validate(self, other: &'v BoxReport, tol: &ReportTolerances,
msg: &str, diffs: &mut fmt::Formatter) -> fmt::Result {
let self_report : &Report = self.deref();
let other_report : &Report = other.deref();
self_report.validate_report(other_report, tol, msg, diffs)
}
}
impl<'v> ApproxEq<ReportTolerances, &'v [BoxReport]> for &'v [BoxReport] {
fn validate(self, other: &'v [BoxReport], tol: &ReportTolerances,
msg: &str, diffs: &mut fmt::Formatter) -> fmt::Result {
if self.len() != other.len() {
write!(diffs, "Slice: length {} != {}", self.len(), other.len())?;
}
for (self_item, other_item) in self.iter().zip(other.iter()) {
self_item.validate(other_item, tol, msg, diffs)?;
}
Ok(())
}
}
pub fn get_report_registry() -> &'static ReportTypeRegistry {
lazy_static! {
static ref REG: ReportTypeRegistry = {
let mut reg = ReportTypeRegistry::new();
reg.insert("DeltaGammaReport", BoxFnSeed::new(DeltaGammaReport::from_serial));
reg.insert("VegaVolgaReport", BoxFnSeed::new(VegaVolgaReport::from_serial));
reg.insert("TimeBumpedReport", BoxFnSeed::new(TimeBumpedReport::from_serial));
reg
};
}
®
}
pub fn bumped_price(bump: &Bump, pricer: &mut Pricer, saveable: Option<&mut Saveable>, unbumped: f64)
-> Result<f64, qm::Error> {
if pricer.as_mut_bumpable().bump(bump, saveable)? {
pricer.price()
} else {
Ok(unbumped)
}
}