rust_order_book/report.rs
1//! Types representing the result of order processing.
2//!
3//! This module defines the output types returned by the order book after
4//! processing orders, such as [`ExecutionReport`] and [`FillReport`].
5//!
6//! These types are used to track the outcome of submitted market or limit orders,
7//! including how much was executed, any remaining quantity, and the resulting trades.
8use crate::{
9 journal::JournalLog,
10 order::{get_order_time_in_force, OrderId, Price, Quantity},
11 OrderStatus, OrderType, Side, TimeInForce,
12};
13
14/// A report for an individual fill that occurred during order execution.
15///
16/// A single order may generate multiple fills if matched across
17/// multiple price levels or counter-orders.
18///
19/// # Fields
20/// - `order_id`: The ID of the counterparty order involved in the fill
21/// - `price`: The execution price
22/// - `quantity`: The quantity filled
23/// - `status`: The status of the order after the fill
24#[derive(Debug)]
25pub struct FillReport {
26 pub order_id: OrderId,
27 pub price: Price,
28 pub quantity: Quantity,
29 pub status: OrderStatus,
30}
31
32#[derive(Debug)]
33pub(crate) struct ExecutionReportParams {
34 pub id: OrderId,
35 pub order_type: OrderType,
36 pub side: Side,
37 pub quantity: Quantity,
38 pub status: OrderStatus,
39 pub time_in_force: Option<TimeInForce>,
40 pub price: Option<Price>,
41 pub post_only: bool,
42}
43
44/// A comprehensive report describing the result of a submitted order.
45///
46/// The report includes the amount filled, remaining quantity, order status,
47/// any matched trades (`fills`), and optional journaling info.
48///
49/// # Fields
50/// - `order_id`: ID assigned to the order
51/// - `orig_qty`: Quantity originally requested
52/// - `executed_qty`: Total quantity filled
53/// - `remaining_qty`: Quantity still unfilled
54/// - `taker_qty`: Quantity matched as taker (aggressive side)
55/// - `maker_qty`: Quantity resting as maker (passive side)
56/// - `order_type`: Market or Limit
57/// - `side`: Buy or Sell
58/// - `price`: For limit orders, this is the limit price; for market is 0
59/// - `status`: Final status of the order
60/// - `time_in_force`: Time-in-force policy applied
61/// - `post_only`: Whether the order was post-only
62/// - `fills`: Vector of individual fills
63/// - `log`: Optional journal log (if journaling is enabled)
64#[derive(Debug)]
65pub struct ExecutionReport {
66 pub order_id: OrderId,
67 pub orig_qty: Quantity,
68 pub executed_qty: Quantity,
69 pub remaining_qty: Quantity,
70 pub taker_qty: Quantity,
71 pub maker_qty: Quantity,
72 pub order_type: OrderType,
73 pub side: Side,
74 pub price: Price,
75 pub status: OrderStatus,
76 pub time_in_force: TimeInForce,
77 pub post_only: bool,
78 pub fills: Vec<FillReport>,
79 pub log: Option<JournalLog>,
80}
81
82impl ExecutionReport {
83 /// Creates a new execution report for a submitted order.
84 ///
85 /// Usually called internally by the order book engine.
86 ///
87 /// # Parameters
88 /// - `id`: The order ID
89 /// - `order_type`: Market or Limit
90 /// - `side`: Buy or Sell
91 /// - `quantity`: Requested quantity
92 /// - `status`: Initial order status (usually `New`)
93 /// - `time_in_force`: Optional TIF value (e.g., GTC, IOC)
94 /// - `price`: Optional limit price (or placeholder for market orders)
95 /// - `post_only`: Whether the order was post-only
96 pub(crate) fn new(params: ExecutionReportParams) -> Self {
97 Self {
98 order_id: params.id,
99 orig_qty: params.quantity,
100 executed_qty: Quantity(0),
101 remaining_qty: params.quantity,
102 status: params.status,
103 taker_qty: Quantity(0),
104 maker_qty: Quantity(0),
105 order_type: params.order_type,
106 side: params.side,
107 price: params.price.unwrap_or(Price(0)),
108 // market order are always IOC
109 time_in_force: if params.order_type == OrderType::Market {
110 TimeInForce::IOC
111 } else {
112 get_order_time_in_force(params.time_in_force)
113 },
114 post_only: params.post_only,
115 fills: Vec::new(),
116 log: None,
117 }
118 }
119}