diff --git a/crates/fidc-core/src/data.rs b/crates/fidc-core/src/data.rs index 41849d0..3a554e8 100644 --- a/crates/fidc-core/src/data.rs +++ b/crates/fidc-core/src/data.rs @@ -493,6 +493,8 @@ struct AdjustedCloseSeries { dates: Vec, backward_factors: Vec>, back_adjusted_closes: Vec>, + back_adjusted_close_prefix: Vec, + missing_back_adjusted_close_prefix: Vec, } impl AdjustedCloseSeries { @@ -502,6 +504,10 @@ impl AdjustedCloseSeries { ) -> Option { let mut backward_factors = Vec::with_capacity(market.dates.len()); let mut back_adjusted_closes = Vec::with_capacity(market.dates.len()); + let mut back_adjusted_close_prefix = Vec::with_capacity(market.dates.len() + 1); + let mut missing_back_adjusted_close_prefix = Vec::with_capacity(market.dates.len() + 1); + back_adjusted_close_prefix.push(0.0); + missing_back_adjusted_close_prefix.push(0); for (date, close) in market.dates.iter().zip(&market.closes) { let factor = factor_by_date .get(date) @@ -515,11 +521,27 @@ impl AdjustedCloseSeries { .map(|factor| close * factor); backward_factors.push(factor); back_adjusted_closes.push(back_adjusted_close); + back_adjusted_close_prefix.push( + back_adjusted_close_prefix + .last() + .copied() + .unwrap_or_default() + + back_adjusted_close.unwrap_or_default(), + ); + missing_back_adjusted_close_prefix.push( + missing_back_adjusted_close_prefix + .last() + .copied() + .unwrap_or_default() + + u32::from(back_adjusted_close.is_none()), + ); } Some(Self { dates: market.dates.clone(), backward_factors, back_adjusted_closes, + back_adjusted_close_prefix, + missing_back_adjusted_close_prefix, }) } @@ -537,10 +559,12 @@ impl AdjustedCloseSeries { } let base_factor = self.backward_factors.get(end - 1).copied().flatten()?; let start = end - lookback; - let sum = self.back_adjusted_closes[start..end] - .iter() - .copied() - .try_fold(0.0, |sum, value| value.map(|value| sum + value))?; + if self.missing_back_adjusted_close_prefix[end] + != self.missing_back_adjusted_close_prefix[start] + { + return None; + } + let sum = self.back_adjusted_close_prefix[end] - self.back_adjusted_close_prefix[start]; if !sum.is_finite() { return None; } @@ -779,10 +803,7 @@ impl SymbolPriceSeries { return None; } let start = end - lookback; - let sum = self.volumes[start..end] - .iter() - .map(|value| *value as f64) - .sum::(); + let sum = self.volume_prefix[end] - self.volume_prefix[start]; if !sum.is_finite() { return None; } @@ -3705,7 +3726,9 @@ mod tests { .map(|index| start + chrono::Duration::days(index as i64)) .collect(), backward_factors: vec![Some(1.0); 30], - back_adjusted_closes: values.into_iter().map(Some).collect(), + back_adjusted_closes: values.iter().copied().map(Some).collect(), + back_adjusted_close_prefix: prefix_sums(&values), + missing_back_adjusted_close_prefix: vec![0; 31], }; let date = *series.dates.last().expect("last date");