use super::config::BacktestConfig;
pub(crate) fn rebalance_cost(
drift: &[f64],
target: &[f64],
dollar_vol: Option<&[f64]>,
cfg: &BacktestConfig,
) -> f64 {
let turnover: f64 = drift.iter().zip(target).map(|(d, t)| (t - d).abs()).sum();
let sells: f64 = drift
.iter()
.zip(target)
.map(|(d, t)| (d - t).max(0.0))
.sum();
let mut cost = (cfg.fee_ratio + cfg.slippage_ratio) * turnover + cfg.tax_ratio * sells;
if cfg.impact_coef > 0.0 && cfg.initial_capital > 0.0 {
if let Some(dv) = dollar_vol {
for ((d, t), &v) in drift.iter().zip(target).zip(dv) {
let dw = (t - d).abs();
if dw == 0.0 || v.is_nan() || v <= 0.0 {
continue;
}
let participation = (dw * cfg.initial_capital / v).min(1.0);
cost += dw * cfg.impact_coef * participation.sqrt();
}
}
}
cost
}