1use std::fmt::Display;
17
18use nautilus_core::{UnixNanos, UUID4};
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 serde::{Deserialize, Serialize};
28
29#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
31#[serde(tag = "type")]
32#[cfg_attr(
33 feature = "python",
34 pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.execution")
35)]
36pub struct OrderStatusReport {
37 pub account_id: AccountId,
39 pub instrument_id: InstrumentId,
41 pub client_order_id: Option<ClientOrderId>,
43 pub venue_order_id: VenueOrderId,
45 pub order_side: OrderSide,
47 pub order_type: OrderType,
49 pub time_in_force: TimeInForce,
51 pub order_status: OrderStatus,
53 pub quantity: Quantity,
55 pub filled_qty: Quantity,
57 pub report_id: UUID4,
59 pub ts_accepted: UnixNanos,
61 pub ts_last: UnixNanos,
63 pub ts_init: UnixNanos,
65 pub order_list_id: Option<OrderListId>,
67 pub venue_position_id: Option<PositionId>,
69 pub contingency_type: ContingencyType,
71 pub expire_time: Option<UnixNanos>,
73 pub price: Option<Price>,
75 pub trigger_price: Option<Price>,
77 pub trigger_type: Option<TriggerType>,
79 pub limit_offset: Option<Price>,
81 pub trailing_offset: Option<Price>,
83 pub trailing_offset_type: TrailingOffsetType,
85 pub avg_px: Option<f64>,
87 pub display_qty: Option<Quantity>,
89 pub post_only: bool,
91 pub reduce_only: bool,
93 pub cancel_reason: Option<String>,
95 pub ts_triggered: Option<UnixNanos>,
97}
98
99impl OrderStatusReport {
100 #[allow(clippy::too_many_arguments)]
102 #[must_use]
103 pub fn new(
104 account_id: AccountId,
105 instrument_id: InstrumentId,
106 client_order_id: Option<ClientOrderId>,
107 venue_order_id: VenueOrderId,
108 order_side: OrderSide,
109 order_type: OrderType,
110 time_in_force: TimeInForce,
111 order_status: OrderStatus,
112 quantity: Quantity,
113 filled_qty: Quantity,
114 ts_accepted: UnixNanos,
115 ts_last: UnixNanos,
116 ts_init: UnixNanos,
117 report_id: Option<UUID4>,
118 ) -> Self {
119 Self {
120 account_id,
121 instrument_id,
122 client_order_id,
123 venue_order_id,
124 order_side,
125 order_type,
126 time_in_force,
127 order_status,
128 quantity,
129 filled_qty,
130 report_id: report_id.unwrap_or_default(),
131 ts_accepted,
132 ts_last,
133 ts_init,
134 order_list_id: None,
135 venue_position_id: None,
136 contingency_type: ContingencyType::default(),
137 expire_time: None,
138 price: None,
139 trigger_price: None,
140 trigger_type: None,
141 limit_offset: None,
142 trailing_offset: None,
143 trailing_offset_type: TrailingOffsetType::default(),
144 avg_px: None,
145 display_qty: None,
146 post_only: false,
147 reduce_only: false,
148 cancel_reason: None,
149 ts_triggered: None,
150 }
151 }
152
153 #[must_use]
155 pub const fn with_client_order_id(mut self, client_order_id: ClientOrderId) -> Self {
156 self.client_order_id = Some(client_order_id);
157 self
158 }
159
160 #[must_use]
162 pub const fn with_order_list_id(mut self, order_list_id: OrderListId) -> Self {
163 self.order_list_id = Some(order_list_id);
164 self
165 }
166
167 #[must_use]
169 pub const fn with_venue_position_id(mut self, venue_position_id: PositionId) -> Self {
170 self.venue_position_id = Some(venue_position_id);
171 self
172 }
173
174 #[must_use]
176 pub const fn with_price(mut self, price: Price) -> Self {
177 self.price = Some(price);
178 self
179 }
180
181 #[must_use]
183 pub const fn with_avg_px(mut self, avg_px: f64) -> Self {
184 self.avg_px = Some(avg_px);
185 self
186 }
187
188 #[must_use]
190 pub const fn with_trigger_price(mut self, trigger_price: Price) -> Self {
191 self.trigger_price = Some(trigger_price);
192 self
193 }
194
195 #[must_use]
197 pub const fn with_trigger_type(mut self, trigger_type: TriggerType) -> Self {
198 self.trigger_type = Some(trigger_type);
199 self
200 }
201
202 #[must_use]
204 pub const fn with_limit_offset(mut self, limit_offset: Price) -> Self {
205 self.limit_offset = Some(limit_offset);
206 self
207 }
208
209 #[must_use]
211 pub const fn with_trailing_offset(mut self, trailing_offset: Price) -> Self {
212 self.trailing_offset = Some(trailing_offset);
213 self
214 }
215
216 #[must_use]
218 pub const fn with_trailing_offset_type(
219 mut self,
220 trailing_offset_type: TrailingOffsetType,
221 ) -> Self {
222 self.trailing_offset_type = trailing_offset_type;
223 self
224 }
225
226 #[must_use]
228 pub const fn with_display_qty(mut self, display_qty: Quantity) -> Self {
229 self.display_qty = Some(display_qty);
230 self
231 }
232
233 #[must_use]
235 pub const fn with_expire_time(mut self, expire_time: UnixNanos) -> Self {
236 self.expire_time = Some(expire_time);
237 self
238 }
239
240 #[must_use]
242 pub const fn with_post_only(mut self, post_only: bool) -> Self {
243 self.post_only = post_only;
244 self
245 }
246
247 #[must_use]
249 pub const fn with_reduce_only(mut self, reduce_only: bool) -> Self {
250 self.reduce_only = reduce_only;
251 self
252 }
253
254 #[must_use]
256 pub fn with_cancel_reason(mut self, cancel_reason: &str) -> Self {
257 self.cancel_reason = Some(cancel_reason.to_string());
258 self
259 }
260
261 #[must_use]
263 pub const fn with_ts_triggered(mut self, ts_triggered: UnixNanos) -> Self {
264 self.ts_triggered = Some(ts_triggered);
265 self
266 }
267
268 #[must_use]
270 pub const fn with_contingency_type(mut self, contingency_type: ContingencyType) -> Self {
271 self.contingency_type = contingency_type;
272 self
273 }
274}
275
276impl Display for OrderStatusReport {
277 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
278 write!(
279 f,
280 "OrderStatusReport(\
281 account_id={}, \
282 instrument_id={}, \
283 venue_order_id={}, \
284 order_side={}, \
285 order_type={}, \
286 time_in_force={}, \
287 order_status={}, \
288 quantity={}, \
289 filled_qty={}, \
290 report_id={}, \
291 ts_accepted={}, \
292 ts_last={}, \
293 ts_init={}, \
294 client_order_id={:?}, \
295 order_list_id={:?}, \
296 venue_position_id={:?}, \
297 contingency_type={}, \
298 expire_time={:?}, \
299 price={:?}, \
300 trigger_price={:?}, \
301 trigger_type={:?}, \
302 limit_offset={:?}, \
303 trailing_offset={:?}, \
304 trailing_offset_type={}, \
305 avg_px={:?}, \
306 display_qty={:?}, \
307 post_only={}, \
308 reduce_only={}, \
309 cancel_reason={:?}, \
310 ts_triggered={:?}\
311 )",
312 self.account_id,
313 self.instrument_id,
314 self.venue_order_id,
315 self.order_side,
316 self.order_type,
317 self.time_in_force,
318 self.order_status,
319 self.quantity,
320 self.filled_qty,
321 self.report_id,
322 self.ts_accepted,
323 self.ts_last,
324 self.ts_init,
325 self.client_order_id,
326 self.order_list_id,
327 self.venue_position_id,
328 self.contingency_type,
329 self.expire_time,
330 self.price,
331 self.trigger_price,
332 self.trigger_type,
333 self.limit_offset,
334 self.trailing_offset,
335 self.trailing_offset_type,
336 self.avg_px,
337 self.display_qty,
338 self.post_only,
339 self.reduce_only,
340 self.cancel_reason,
341 self.ts_triggered,
342 )
343 }
344}