1use std::fmt::Display;
17
18use nautilus_core::{UUID4, UnixNanos};
19use nautilus_model::{
20 enums::{
21 ContingencyType, OrderSide, OrderStatus, OrderType, TimeInForce, TrailingOffsetType,
22 TriggerType,
23 },
24 identifiers::{AccountId, ClientOrderId, InstrumentId, OrderListId, PositionId, VenueOrderId},
25 types::{Price, Quantity},
26};
27use rust_decimal::Decimal;
28use serde::{Deserialize, Serialize};
29
30#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
32#[serde(tag = "type")]
33#[cfg_attr(
34 feature = "python",
35 pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.execution")
36)]
37pub struct OrderStatusReport {
38 pub account_id: AccountId,
40 pub instrument_id: InstrumentId,
42 pub client_order_id: Option<ClientOrderId>,
44 pub venue_order_id: VenueOrderId,
46 pub order_side: OrderSide,
48 pub order_type: OrderType,
50 pub time_in_force: TimeInForce,
52 pub order_status: OrderStatus,
54 pub quantity: Quantity,
56 pub filled_qty: Quantity,
58 pub report_id: UUID4,
60 pub ts_accepted: UnixNanos,
62 pub ts_last: UnixNanos,
64 pub ts_init: UnixNanos,
66 pub order_list_id: Option<OrderListId>,
68 pub venue_position_id: Option<PositionId>,
70 pub contingency_type: ContingencyType,
72 pub expire_time: Option<UnixNanos>,
74 pub price: Option<Price>,
76 pub trigger_price: Option<Price>,
78 pub trigger_type: Option<TriggerType>,
80 pub limit_offset: Option<Decimal>,
82 pub trailing_offset: Option<Decimal>,
84 pub trailing_offset_type: TrailingOffsetType,
86 pub avg_px: Option<f64>,
88 pub display_qty: Option<Quantity>,
90 pub post_only: bool,
92 pub reduce_only: bool,
94 pub cancel_reason: Option<String>,
96 pub ts_triggered: Option<UnixNanos>,
98}
99
100impl OrderStatusReport {
101 #[allow(clippy::too_many_arguments)]
103 #[must_use]
104 pub fn new(
105 account_id: AccountId,
106 instrument_id: InstrumentId,
107 client_order_id: Option<ClientOrderId>,
108 venue_order_id: VenueOrderId,
109 order_side: OrderSide,
110 order_type: OrderType,
111 time_in_force: TimeInForce,
112 order_status: OrderStatus,
113 quantity: Quantity,
114 filled_qty: Quantity,
115 ts_accepted: UnixNanos,
116 ts_last: UnixNanos,
117 ts_init: UnixNanos,
118 report_id: Option<UUID4>,
119 ) -> Self {
120 Self {
121 account_id,
122 instrument_id,
123 client_order_id,
124 venue_order_id,
125 order_side,
126 order_type,
127 time_in_force,
128 order_status,
129 quantity,
130 filled_qty,
131 report_id: report_id.unwrap_or_default(),
132 ts_accepted,
133 ts_last,
134 ts_init,
135 order_list_id: None,
136 venue_position_id: None,
137 contingency_type: ContingencyType::default(),
138 expire_time: None,
139 price: None,
140 trigger_price: None,
141 trigger_type: None,
142 limit_offset: None,
143 trailing_offset: None,
144 trailing_offset_type: TrailingOffsetType::default(),
145 avg_px: None,
146 display_qty: None,
147 post_only: false,
148 reduce_only: false,
149 cancel_reason: None,
150 ts_triggered: None,
151 }
152 }
153
154 #[must_use]
156 pub const fn with_client_order_id(mut self, client_order_id: ClientOrderId) -> Self {
157 self.client_order_id = Some(client_order_id);
158 self
159 }
160
161 #[must_use]
163 pub const fn with_order_list_id(mut self, order_list_id: OrderListId) -> Self {
164 self.order_list_id = Some(order_list_id);
165 self
166 }
167
168 #[must_use]
170 pub const fn with_venue_position_id(mut self, venue_position_id: PositionId) -> Self {
171 self.venue_position_id = Some(venue_position_id);
172 self
173 }
174
175 #[must_use]
177 pub const fn with_price(mut self, price: Price) -> Self {
178 self.price = Some(price);
179 self
180 }
181
182 #[must_use]
184 pub const fn with_avg_px(mut self, avg_px: f64) -> Self {
185 self.avg_px = Some(avg_px);
186 self
187 }
188
189 #[must_use]
191 pub const fn with_trigger_price(mut self, trigger_price: Price) -> Self {
192 self.trigger_price = Some(trigger_price);
193 self
194 }
195
196 #[must_use]
198 pub const fn with_trigger_type(mut self, trigger_type: TriggerType) -> Self {
199 self.trigger_type = Some(trigger_type);
200 self
201 }
202
203 #[must_use]
205 pub const fn with_limit_offset(mut self, limit_offset: Decimal) -> Self {
206 self.limit_offset = Some(limit_offset);
207 self
208 }
209
210 #[must_use]
212 pub const fn with_trailing_offset(mut self, trailing_offset: Decimal) -> Self {
213 self.trailing_offset = Some(trailing_offset);
214 self
215 }
216
217 #[must_use]
219 pub const fn with_trailing_offset_type(
220 mut self,
221 trailing_offset_type: TrailingOffsetType,
222 ) -> Self {
223 self.trailing_offset_type = trailing_offset_type;
224 self
225 }
226
227 #[must_use]
229 pub const fn with_display_qty(mut self, display_qty: Quantity) -> Self {
230 self.display_qty = Some(display_qty);
231 self
232 }
233
234 #[must_use]
236 pub const fn with_expire_time(mut self, expire_time: UnixNanos) -> Self {
237 self.expire_time = Some(expire_time);
238 self
239 }
240
241 #[must_use]
243 pub const fn with_post_only(mut self, post_only: bool) -> Self {
244 self.post_only = post_only;
245 self
246 }
247
248 #[must_use]
250 pub const fn with_reduce_only(mut self, reduce_only: bool) -> Self {
251 self.reduce_only = reduce_only;
252 self
253 }
254
255 #[must_use]
257 pub fn with_cancel_reason(mut self, cancel_reason: String) -> Self {
258 self.cancel_reason = Some(cancel_reason);
259 self
260 }
261
262 #[must_use]
264 pub const fn with_ts_triggered(mut self, ts_triggered: UnixNanos) -> Self {
265 self.ts_triggered = Some(ts_triggered);
266 self
267 }
268
269 #[must_use]
271 pub const fn with_contingency_type(mut self, contingency_type: ContingencyType) -> Self {
272 self.contingency_type = contingency_type;
273 self
274 }
275}
276
277impl Display for OrderStatusReport {
278 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
279 write!(
280 f,
281 "OrderStatusReport(\
282 account_id={}, \
283 instrument_id={}, \
284 venue_order_id={}, \
285 order_side={}, \
286 order_type={}, \
287 time_in_force={}, \
288 order_status={}, \
289 quantity={}, \
290 filled_qty={}, \
291 report_id={}, \
292 ts_accepted={}, \
293 ts_last={}, \
294 ts_init={}, \
295 client_order_id={:?}, \
296 order_list_id={:?}, \
297 venue_position_id={:?}, \
298 contingency_type={}, \
299 expire_time={:?}, \
300 price={:?}, \
301 trigger_price={:?}, \
302 trigger_type={:?}, \
303 limit_offset={:?}, \
304 trailing_offset={:?}, \
305 trailing_offset_type={}, \
306 avg_px={:?}, \
307 display_qty={:?}, \
308 post_only={}, \
309 reduce_only={}, \
310 cancel_reason={:?}, \
311 ts_triggered={:?}\
312 )",
313 self.account_id,
314 self.instrument_id,
315 self.venue_order_id,
316 self.order_side,
317 self.order_type,
318 self.time_in_force,
319 self.order_status,
320 self.quantity,
321 self.filled_qty,
322 self.report_id,
323 self.ts_accepted,
324 self.ts_last,
325 self.ts_init,
326 self.client_order_id,
327 self.order_list_id,
328 self.venue_position_id,
329 self.contingency_type,
330 self.expire_time,
331 self.price,
332 self.trigger_price,
333 self.trigger_type,
334 self.limit_offset,
335 self.trailing_offset,
336 self.trailing_offset_type,
337 self.avg_px,
338 self.display_qty,
339 self.post_only,
340 self.reduce_only,
341 self.cancel_reason,
342 self.ts_triggered,
343 )
344 }
345}