完善平台策略回测撮合和滑点
This commit is contained in:
@@ -270,15 +270,31 @@ impl Position {
|
||||
}
|
||||
|
||||
pub fn apply_cash_dividend(&mut self, dividend_per_share: f64) -> f64 {
|
||||
self.apply_cash_dividend_internal(dividend_per_share, true)
|
||||
}
|
||||
|
||||
pub fn apply_cash_dividend_preserve_cost_basis(&mut self, dividend_per_share: f64) -> f64 {
|
||||
self.apply_cash_dividend_internal(dividend_per_share, false)
|
||||
}
|
||||
|
||||
fn apply_cash_dividend_internal(
|
||||
&mut self,
|
||||
dividend_per_share: f64,
|
||||
adjust_cost_basis: bool,
|
||||
) -> f64 {
|
||||
if self.quantity == 0 || !dividend_per_share.is_finite() || dividend_per_share == 0.0 {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
for lot in &mut self.lots {
|
||||
lot.entry_price -= dividend_per_share;
|
||||
lot.price -= dividend_per_share;
|
||||
if adjust_cost_basis {
|
||||
lot.price -= dividend_per_share;
|
||||
}
|
||||
}
|
||||
if adjust_cost_basis {
|
||||
self.average_cost -= dividend_per_share;
|
||||
}
|
||||
self.average_cost -= dividend_per_share;
|
||||
self.last_price -= dividend_per_share;
|
||||
let cash_delta = self.quantity as f64 * dividend_per_share;
|
||||
self.day_dividend_cash += cash_delta;
|
||||
@@ -887,6 +903,23 @@ mod tests {
|
||||
assert!((position.holding_return(6.06).unwrap() - (6.06 / 5.66 - 1.0)).abs() < 1e-12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cash_dividend_can_preserve_avg_cost_for_aiquant_compatibility() {
|
||||
let date = NaiveDate::from_ymd_opt(2025, 1, 2).unwrap();
|
||||
let mut position = Position::new("603102.SH");
|
||||
position.buy(date, 1000, 46.45);
|
||||
position.record_buy_trade_cost(1000, 37.16);
|
||||
|
||||
let cost_before = position.average_cost;
|
||||
let entry_before = position.average_entry_price().unwrap();
|
||||
let cash = position.apply_cash_dividend_preserve_cost_basis(0.6);
|
||||
|
||||
assert!((cash - 600.0).abs() < 1e-12);
|
||||
assert!((position.average_cost - cost_before).abs() < 1e-12);
|
||||
assert!((position.average_entry_price().unwrap() - (entry_before - 0.6)).abs() < 1e-12);
|
||||
assert!((position.last_price - 45.85).abs() < 1e-12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn portfolio_tracks_dividend_receivable_and_day_pnl() {
|
||||
let prev_date = NaiveDate::from_ymd_opt(2025, 1, 2).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user