use crate::{
core::marketdatahandling::{
discountrequest::DiscountRequest, forwardraterequest::ForwardRateRequest,
fxrequest::FxRequest, pathdependentrequest::PathDependentRequest, spotrequest::SpotRequest,
},
time::date::Date,
xva::nettingset::NettingSet,
};
use super::{
claimcompressionpreprocessor::ClaimCompressionPreprocessor,
claimpreprocessor::ClaimPreprocessor,
};
#[derive(Default, Clone)]
pub struct SimulationRequest {
pub expiration_date: Option<Date>,
pub discount_request: Option<DiscountRequest>,
pub forward_rate_request: Option<ForwardRateRequest>,
pub fx_request: Option<FxRequest>,
pub spot_request: Option<SpotRequest>,
pub path_dependent_request: Option<PathDependentRequest>,
}
impl SimulationRequest {
#[must_use]
pub fn is_active_on(&self, evaluation_date: Date) -> bool {
self.expiration_date
.is_none_or(|expiration| evaluation_date < expiration)
}
}
pub struct PreprocessorExecutor {
requests: Vec<SimulationRequest>,
preprocessors: Vec<Box<dyn ClaimPreprocessor>>,
compress: bool,
}
impl Default for PreprocessorExecutor {
fn default() -> Self {
Self::new()
}
}
impl PreprocessorExecutor {
#[must_use]
pub fn new() -> Self {
Self {
requests: Vec::new(),
preprocessors: Vec::new(),
compress: false,
}
}
#[must_use]
pub fn with_preprocessor(mut self, preprocessor: Box<dyn ClaimPreprocessor>) -> Self {
self.preprocessors.push(preprocessor);
self
}
#[must_use]
pub const fn with_compression(mut self) -> Self {
self.compress = true;
self
}
pub fn visit<'a>(&mut self, netting_sets: impl IntoIterator<Item = &'a mut NettingSet>) {
self.requests.clear();
let mut global_idx = 0;
for ns in netting_sets {
for claim in ns.claims_mut() {
for pp in &self.preprocessors {
pp.process(claim);
}
}
if self.compress {
ClaimCompressionPreprocessor::compress(ns.claims_vec_mut());
}
let (policy, claims) = ns.discount_policy_and_claims_mut();
for claim in claims {
let mut requests = claim.simulation_requests();
for request in &mut requests {
request.expiration_date = Some(claim.payment_date());
}
if let Ok(discount_index) = policy.accept(claim) {
requests[0].discount_request =
Some(DiscountRequest::new(discount_index, claim.payment_date()));
}
claim.set_idx(global_idx);
global_idx += requests.len();
self.requests.extend(requests);
}
}
}
#[must_use]
pub fn requests(&self) -> &[SimulationRequest] {
&self.requests
}
}