fix: tolerate missing holding market rows

This commit is contained in:
boris
2026-04-24 12:51:47 -07:00
parent bd9b26deb3
commit 60f0f73076
4 changed files with 336 additions and 17 deletions

View File

@@ -3841,8 +3841,14 @@ where
) -> Result<f64, BacktestError> {
let mut market_value = 0.0;
for position in portfolio.positions().values() {
let price = data.price(date, &position.symbol, field).ok_or_else(|| {
BacktestError::MissingPrice {
let price = data
.price(date, &position.symbol, field)
.or_else(|| data.price_on_or_before(date, &position.symbol, field))
.or_else(|| {
(position.last_price.is_finite() && position.last_price > 0.0)
.then_some(position.last_price)
})
.ok_or_else(|| BacktestError::MissingPrice {
date,
symbol: position.symbol.clone(),
field: match field {
@@ -3851,8 +3857,7 @@ where
PriceField::Close => "close",
PriceField::Last => "last",
},
}
})?;
})?;
market_value += price * position.quantity as f64;
}
@@ -3962,12 +3967,32 @@ where
) -> Result<f64, BacktestError> {
let mut market_value = 0.0;
for position in portfolio.positions().values() {
let price = self.rebalance_valuation_price_with_overrides(
date,
&position.symbol,
data,
valuation_prices,
)?;
let price = if valuation_prices.is_some() {
self.rebalance_valuation_price_with_overrides(
date,
&position.symbol,
data,
valuation_prices,
)?
} else if let Some(snapshot) = data.market(date, &position.symbol) {
self.rebalance_valuation_price_for_snapshot(snapshot)
.ok_or_else(|| BacktestError::MissingPrice {
date,
symbol: position.symbol.clone(),
field: self.rebalance_valuation_price_field_name(),
})?
} else {
data.price_on_or_before(date, &position.symbol, PriceField::Close)
.or_else(|| {
(position.last_price.is_finite() && position.last_price > 0.0)
.then_some(position.last_price)
})
.ok_or_else(|| BacktestError::MissingPrice {
date,
symbol: position.symbol.clone(),
field: self.rebalance_valuation_price_field_name(),
})?
};
market_value += price * position.quantity as f64;
}
Ok(portfolio.cash() + market_value)