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