Align order lifecycle with rqalpha close semantics
This commit is contained in:
@@ -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(),
|
||||
|
||||
@@ -330,11 +330,6 @@ where
|
||||
ProcessEventKind::PostOnDay,
|
||||
"on_day:post",
|
||||
);
|
||||
let daily_fill_count = report.fill_events.len();
|
||||
let day_orders = report.order_events.clone();
|
||||
let day_fills = report.fill_events.clone();
|
||||
let broker_diagnostics = report.diagnostics.clone();
|
||||
self.extend_result(&mut result, report);
|
||||
|
||||
portfolio.update_prices(execution_date, &self.data, PriceField::Close)?;
|
||||
|
||||
@@ -358,6 +353,13 @@ where
|
||||
ProcessEventKind::AfterTrading,
|
||||
"after_trading",
|
||||
);
|
||||
let mut close_report = self.broker.after_trading(execution_date);
|
||||
process_events.append(&mut close_report.process_events);
|
||||
report.order_events.extend(close_report.order_events);
|
||||
report.fill_events.extend(close_report.fill_events);
|
||||
report.position_events.extend(close_report.position_events);
|
||||
report.account_events.extend(close_report.account_events);
|
||||
report.diagnostics.extend(close_report.diagnostics);
|
||||
push_phase_event(
|
||||
&mut process_events,
|
||||
execution_date,
|
||||
@@ -383,6 +385,11 @@ where
|
||||
ProcessEventKind::PostSettlement,
|
||||
"settlement:post",
|
||||
);
|
||||
let daily_fill_count = report.fill_events.len();
|
||||
let day_orders = report.order_events.clone();
|
||||
let day_fills = report.fill_events.clone();
|
||||
let broker_diagnostics = report.diagnostics.clone();
|
||||
self.extend_result(&mut result, report);
|
||||
|
||||
let benchmark =
|
||||
self.data
|
||||
|
||||
@@ -110,6 +110,8 @@ pub enum ProcessEventKind {
|
||||
PostSettlement,
|
||||
OrderPendingNew,
|
||||
OrderCreationPass,
|
||||
OrderPendingCancel,
|
||||
OrderCancellationPass,
|
||||
OrderUnsolicitedUpdate,
|
||||
Trade,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user