修正部分卖出持仓成本
This commit is contained in:
@@ -117,6 +117,7 @@ impl Position {
|
||||
let mut remaining = quantity;
|
||||
let mut realized = 0.0;
|
||||
let mut realized_entry = 0.0;
|
||||
let average_cost_before_sell = self.average_cost;
|
||||
|
||||
while remaining > 0 {
|
||||
let Some(first_lot) = self.lots.first_mut() else {
|
||||
@@ -141,7 +142,13 @@ impl Position {
|
||||
self.day_trade_quantity_delta -= quantity as i32;
|
||||
self.day_sell_quantity += quantity;
|
||||
self.day_sell_value += execution_price * quantity as f64;
|
||||
self.recalculate_average_cost();
|
||||
if self.quantity == 0 {
|
||||
self.recalculate_average_cost();
|
||||
} else if average_cost_before_sell.is_finite() && average_cost_before_sell > 0.0 {
|
||||
self.average_cost = average_cost_before_sell;
|
||||
} else {
|
||||
self.recalculate_average_cost();
|
||||
}
|
||||
self.refresh_day_pnl();
|
||||
Ok(realized)
|
||||
}
|
||||
@@ -955,6 +962,26 @@ mod tests {
|
||||
assert!((position.holding_return(6.06).unwrap() - (6.06 / 5.66 - 1.0)).abs() < 1e-12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn partial_sell_preserves_remaining_average_cost() {
|
||||
let date = NaiveDate::from_ymd_opt(2025, 1, 2).unwrap();
|
||||
let mut position = Position::new("603958.SH");
|
||||
position.buy(date, 800, 18.0981);
|
||||
position.record_buy_trade_cost(800, 5.0);
|
||||
position.buy(date, 1700, 19.4694);
|
||||
position.record_buy_trade_cost(1700, 8.27451625);
|
||||
position.buy(date, 200, 18.4584);
|
||||
position.record_buy_trade_cost(200, 5.0);
|
||||
position.buy(date, 100, 17.8378);
|
||||
position.record_buy_trade_cost(100, 5.0);
|
||||
let average_cost_before = position.average_cost;
|
||||
|
||||
position.sell(2700, 16.8331).expect("partial sell");
|
||||
|
||||
assert_eq!(position.quantity, 100);
|
||||
assert!((position.average_cost - average_cost_before).abs() < 1e-12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn holdings_summary_reports_entry_price_pnl_excluding_buy_commission() {
|
||||
let date = NaiveDate::from_ymd_opt(2025, 1, 2).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user