修正滑点成交后的持仓估值
This commit is contained in:
@@ -66,6 +66,16 @@ impl Position {
|
||||
}
|
||||
|
||||
pub fn buy(&mut self, date: NaiveDate, quantity: u32, price: f64) {
|
||||
self.buy_with_mark_price(date, quantity, price, price);
|
||||
}
|
||||
|
||||
pub fn buy_with_mark_price(
|
||||
&mut self,
|
||||
date: NaiveDate,
|
||||
quantity: u32,
|
||||
execution_price: f64,
|
||||
mark_price: f64,
|
||||
) {
|
||||
if quantity == 0 {
|
||||
return;
|
||||
}
|
||||
@@ -73,19 +83,28 @@ impl Position {
|
||||
self.lots.push(PositionLot {
|
||||
acquired_date: date,
|
||||
quantity,
|
||||
entry_price: price,
|
||||
price,
|
||||
entry_price: execution_price,
|
||||
price: execution_price,
|
||||
});
|
||||
self.quantity += quantity;
|
||||
self.last_price = price;
|
||||
self.last_price = normalized_mark_price(mark_price, execution_price);
|
||||
self.day_trade_quantity_delta += quantity as i32;
|
||||
self.day_buy_quantity += quantity;
|
||||
self.day_buy_value += price * quantity as f64;
|
||||
self.day_buy_value += execution_price * quantity as f64;
|
||||
self.recalculate_average_cost();
|
||||
self.refresh_day_pnl();
|
||||
}
|
||||
|
||||
pub fn sell(&mut self, quantity: u32, price: f64) -> Result<f64, String> {
|
||||
self.sell_with_mark_price(quantity, price, price)
|
||||
}
|
||||
|
||||
pub fn sell_with_mark_price(
|
||||
&mut self,
|
||||
quantity: u32,
|
||||
execution_price: f64,
|
||||
mark_price: f64,
|
||||
) -> Result<f64, String> {
|
||||
if quantity > self.quantity {
|
||||
return Err(format!(
|
||||
"sell quantity {} exceeds current quantity {} for {}",
|
||||
@@ -102,7 +121,7 @@ impl Position {
|
||||
};
|
||||
|
||||
let lot_sell = remaining.min(first_lot.quantity);
|
||||
realized += (price - first_lot.price) * lot_sell as f64;
|
||||
realized += (execution_price - first_lot.price) * lot_sell as f64;
|
||||
first_lot.quantity -= lot_sell;
|
||||
remaining -= lot_sell;
|
||||
|
||||
@@ -112,11 +131,11 @@ impl Position {
|
||||
}
|
||||
|
||||
self.quantity -= quantity;
|
||||
self.last_price = price;
|
||||
self.last_price = normalized_mark_price(mark_price, execution_price);
|
||||
self.realized_pnl += realized;
|
||||
self.day_trade_quantity_delta -= quantity as i32;
|
||||
self.day_sell_quantity += quantity;
|
||||
self.day_sell_value += price * quantity as f64;
|
||||
self.day_sell_value += execution_price * quantity as f64;
|
||||
self.recalculate_average_cost();
|
||||
self.refresh_day_pnl();
|
||||
Ok(realized)
|
||||
@@ -356,6 +375,14 @@ impl Position {
|
||||
}
|
||||
}
|
||||
|
||||
fn normalized_mark_price(mark_price: f64, fallback: f64) -> f64 {
|
||||
if mark_price.is_finite() && mark_price > 0.0 {
|
||||
mark_price
|
||||
} else {
|
||||
fallback
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PortfolioState {
|
||||
initial_cash: f64,
|
||||
|
||||
Reference in New Issue
Block a user