Align order lifecycle with rqalpha close semantics

This commit is contained in:
boris
2026-04-23 03:41:49 -07:00
parent 8906490a40
commit b657205103
5 changed files with 314 additions and 27 deletions

View File

@@ -43,6 +43,8 @@ struct OpenOrder {
order_id: u64,
symbol: String,
side: OrderSide,
requested_quantity: u32,
filled_quantity: u32,
remaining_quantity: u32,
limit_price: f64,
reason: String,
@@ -947,7 +949,7 @@ where
}
};
if let Some(order) = canceled {
self.emit_canceled_open_order(date, order, reason, report);
self.emit_user_canceled_open_order(date, order, reason, report);
}
}
@@ -973,7 +975,7 @@ where
canceled
};
for order in canceled {
self.emit_canceled_open_order(date, order, reason, report);
self.emit_user_canceled_open_order(date, order, reason, report);
}
}
@@ -988,38 +990,87 @@ where
std::mem::take(&mut *open_orders)
};
for order in canceled {
self.emit_canceled_open_order(date, order, reason, report);
self.emit_user_canceled_open_order(date, order, reason, report);
}
}
fn emit_canceled_open_order(
fn emit_user_canceled_open_order(
&self,
date: NaiveDate,
order: OpenOrder,
reason: &str,
report: &mut BrokerExecutionReport,
) {
Self::emit_order_process_event(
report,
date,
ProcessEventKind::OrderPendingCancel,
order.order_id,
&order.symbol,
order.side,
format!("reason={reason}"),
);
report.order_events.push(OrderEvent {
date,
order_id: Some(order.order_id),
symbol: order.symbol.clone(),
side: order.side,
requested_quantity: order.remaining_quantity,
filled_quantity: 0,
requested_quantity: order.requested_quantity,
filled_quantity: order.filled_quantity,
status: OrderStatus::Canceled,
reason: format!("{reason}: canceled open order"),
reason: format!("{reason}: canceled by user"),
});
Self::emit_order_process_event(
report,
date,
ProcessEventKind::OrderUnsolicitedUpdate,
ProcessEventKind::OrderCancellationPass,
order.order_id,
&order.symbol,
order.side,
"status=Canceled reason=canceled open order",
format!(
"status=Canceled requested_quantity={} filled_quantity={}",
order.requested_quantity, order.filled_quantity
),
);
}
pub fn after_trading(&self, date: NaiveDate) -> BrokerExecutionReport {
let mut report = BrokerExecutionReport::default();
let pending = {
let mut open_orders = self.open_orders.borrow_mut();
std::mem::take(&mut *open_orders)
};
for order in pending {
let market_close_reason = format!(
"Order Rejected: {} can not match. Market close.",
order.symbol
);
report.order_events.push(OrderEvent {
date,
order_id: Some(order.order_id),
symbol: order.symbol.clone(),
side: order.side,
requested_quantity: order.requested_quantity,
filled_quantity: order.filled_quantity,
status: OrderStatus::Rejected,
reason: market_close_reason.clone(),
});
Self::emit_order_process_event(
&mut report,
date,
ProcessEventKind::OrderUnsolicitedUpdate,
order.order_id,
&order.symbol,
order.side,
format!(
"status=Rejected requested_quantity={} filled_quantity={} reason={market_close_reason}",
order.requested_quantity, order.filled_quantity
),
);
}
report
}
fn emit_order_process_event(
report: &mut BrokerExecutionReport,
date: NaiveDate,
@@ -1583,6 +1634,8 @@ where
order_id,
symbol: symbol.to_string(),
side: OrderSide::Sell,
requested_quantity: requested_qty,
filled_quantity: 0,
remaining_quantity: requested_qty,
limit_price: limit_price.expect("limit price for pending limit sell"),
reason: reason.to_string(),
@@ -1642,6 +1695,8 @@ where
order_id,
symbol: symbol.to_string(),
side: OrderSide::Sell,
requested_quantity: requested_qty,
filled_quantity: 0,
remaining_quantity: requested_qty,
limit_price: limit_price.expect("limit price for pending limit sell"),
reason: reason.to_string(),
@@ -1748,6 +1803,8 @@ where
order_id,
symbol: symbol.to_string(),
side: OrderSide::Sell,
requested_quantity: requested_qty,
filled_quantity: 0,
remaining_quantity: requested_qty,
limit_price: limit_price.expect("limit price for pending limit sell"),
reason: reason.to_string(),
@@ -1883,6 +1940,8 @@ where
order_id,
symbol: symbol.to_string(),
side: OrderSide::Sell,
requested_quantity: requested_qty,
filled_quantity: filled_qty,
remaining_quantity: remaining_qty,
limit_price: limit_price.expect("limit price for pending limit sell"),
reason: reason.to_string(),
@@ -2639,6 +2698,8 @@ where
order_id,
symbol: symbol.to_string(),
side: OrderSide::Buy,
requested_quantity: requested_qty,
filled_quantity: 0,
remaining_quantity: requested_qty,
limit_price: limit_price.expect("limit price for pending limit buy"),
reason: reason.to_string(),
@@ -2770,6 +2831,8 @@ where
order_id,
symbol: symbol.to_string(),
side: OrderSide::Buy,
requested_quantity: requested_qty,
filled_quantity: 0,
remaining_quantity: requested_qty,
limit_price: limit_price.expect("limit price for pending limit buy"),
reason: reason.to_string(),
@@ -2902,6 +2965,8 @@ where
order_id,
symbol: symbol.to_string(),
side: OrderSide::Buy,
requested_quantity: requested_qty,
filled_quantity: filled_qty,
remaining_quantity: remaining_qty,
limit_price: limit_price.expect("limit price for pending limit buy"),
reason: reason.to_string(),