use risk::Bumpable;
use dates::Date;
use dates::datetime::DateTime;
use core::qm;
use std::collections::HashMap;
use instruments::Instrument;
use instruments::RcInstrument;
use instruments::fix_all;
use instruments::PricingContext;
use data::fixings::FixingTable;
use data::bumpspotdate::BumpSpotDate;
use data::bumpspotdate::SpotDynamics;
use data::bump::Bump;
use risk::dependencies::DependencyCollector;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct BumpTime {
spot_date_bump: BumpSpotDate,
_ex_from: Date
}
impl BumpTime {
pub fn new(spot_date: Date, ex_from: Date, spot_dynamics: SpotDynamics) -> BumpTime {
BumpTime { spot_date_bump: BumpSpotDate::new(spot_date, spot_dynamics),
_ex_from: ex_from }
}
pub fn apply(&self, instruments: &mut Vec<(f64, RcInstrument)>,
bumpable: &mut Bumpable) -> Result<bool, qm::Error> {
let modified = self.update_instruments(
instruments, bumpable.context(), bumpable.dependencies()?)?;
let bump = Bump::new_spot_date(self.spot_date_bump.clone());
bumpable.bump(&bump, None)?;
Ok(modified)
}
pub fn update_instruments(&self, instruments: &mut Vec<(f64, RcInstrument)>,
context: &PricingContext, dependencies: &DependencyCollector) -> Result<bool, qm::Error> {
let old_spot_date = context.spot_date();
let new_spot_date = self.spot_date_bump.spot_date();
let mut fixing_map = HashMap::new();
for (id, instrument) in dependencies.instruments_iter() {
for fixing in dependencies.fixings(id).iter() {
let date = fixing.date();
if date >= old_spot_date && date < new_spot_date {
let value = match self.spot_date_bump.spot_dynamics() {
SpotDynamics::StickyForward => {
let inst: &Instrument = &*instrument.clone();
let curve = context.forward_curve(inst, new_spot_date)?;
curve.forward(date)? },
SpotDynamics::StickySpot => {
context.spot(id)? }
};
fixing_map.entry(id.to_string()).or_insert(Vec::<(DateTime, f64)>::new())
.push((*fixing, value));
}
}
}
let mut any_changes = !fixing_map.is_empty();
if any_changes {
let fixing_table = FixingTable::from_iter_known_until(new_spot_date, fixing_map.iter())?;
if let Some(ref mut replacement) = fix_all(instruments, &fixing_table)? {
instruments.clear();
instruments.append(replacement);
} else {
any_changes = false;
}
}
Ok(any_changes)
}
}