1use nautilus_core::{UUID4, UnixNanos};
19use nautilus_model::{
20 enums::{AccountType, LiquiditySide},
21 events::{
22 AccountState, OrderAccepted, OrderCancelRejected, OrderCanceled, OrderDenied,
23 OrderEventAny, OrderExpired, OrderFilled, OrderModifyRejected, OrderRejected,
24 OrderSubmitted, OrderTriggered, OrderUpdated,
25 },
26 identifiers::{AccountId, PositionId, TradeId, TraderId, VenueOrderId},
27 orders::{Order, OrderAny},
28 types::{AccountBalance, Currency, MarginBalance, Money, Price, Quantity},
29};
30
31#[derive(Debug, Clone)]
37pub struct OrderEventFactory {
38 trader_id: TraderId,
39 account_id: AccountId,
40 account_type: AccountType,
41 base_currency: Option<Currency>,
42}
43
44impl OrderEventFactory {
45 #[must_use]
47 pub fn new(
48 trader_id: TraderId,
49 account_id: AccountId,
50 account_type: AccountType,
51 base_currency: Option<Currency>,
52 ) -> Self {
53 Self {
54 trader_id,
55 account_id,
56 account_type,
57 base_currency,
58 }
59 }
60
61 #[must_use]
63 pub fn trader_id(&self) -> TraderId {
64 self.trader_id
65 }
66
67 #[must_use]
69 pub fn account_id(&self) -> AccountId {
70 self.account_id
71 }
72
73 pub const fn set_account_id(&mut self, account_id: AccountId) {
75 self.account_id = account_id;
76 }
77
78 #[must_use]
80 pub fn generate_account_state(
81 &self,
82 balances: Vec<AccountBalance>,
83 margins: Vec<MarginBalance>,
84 reported: bool,
85 ts_event: UnixNanos,
86 ts_init: UnixNanos,
87 ) -> AccountState {
88 AccountState::new(
89 self.account_id,
90 self.account_type,
91 balances,
92 margins,
93 reported,
94 UUID4::new(),
95 ts_event,
96 ts_init,
97 self.base_currency,
98 )
99 }
100
101 #[must_use]
105 pub fn generate_order_denied(
106 &self,
107 order: &OrderAny,
108 reason: &str,
109 ts_init: UnixNanos,
110 ) -> OrderEventAny {
111 let event = OrderDenied::new(
112 self.trader_id,
113 order.strategy_id(),
114 order.instrument_id(),
115 order.client_order_id(),
116 reason.into(),
117 UUID4::new(),
118 ts_init,
119 ts_init,
120 );
121 OrderEventAny::Denied(event)
122 }
123
124 #[must_use]
128 pub fn generate_order_submitted(&self, order: &OrderAny, ts_init: UnixNanos) -> OrderEventAny {
129 let event = OrderSubmitted::new(
130 self.trader_id,
131 order.strategy_id(),
132 order.instrument_id(),
133 order.client_order_id(),
134 self.account_id,
135 UUID4::new(),
136 ts_init,
137 ts_init,
138 );
139 OrderEventAny::Submitted(event)
140 }
141
142 #[must_use]
144 pub fn generate_order_rejected(
145 &self,
146 order: &OrderAny,
147 reason: &str,
148 ts_event: UnixNanos,
149 ts_init: UnixNanos,
150 due_post_only: bool,
151 ) -> OrderEventAny {
152 let event = OrderRejected::new(
153 self.trader_id,
154 order.strategy_id(),
155 order.instrument_id(),
156 order.client_order_id(),
157 self.account_id,
158 reason.into(),
159 UUID4::new(),
160 ts_event,
161 ts_init,
162 false,
163 due_post_only,
164 );
165 OrderEventAny::Rejected(event)
166 }
167
168 #[must_use]
170 pub fn generate_order_accepted(
171 &self,
172 order: &OrderAny,
173 venue_order_id: VenueOrderId,
174 ts_event: UnixNanos,
175 ts_init: UnixNanos,
176 ) -> OrderEventAny {
177 let event = OrderAccepted::new(
178 self.trader_id,
179 order.strategy_id(),
180 order.instrument_id(),
181 order.client_order_id(),
182 venue_order_id,
183 self.account_id,
184 UUID4::new(),
185 ts_event,
186 ts_init,
187 false,
188 );
189 OrderEventAny::Accepted(event)
190 }
191
192 #[must_use]
194 pub fn generate_order_modify_rejected(
195 &self,
196 order: &OrderAny,
197 venue_order_id: Option<VenueOrderId>,
198 reason: &str,
199 ts_event: UnixNanos,
200 ts_init: UnixNanos,
201 ) -> OrderEventAny {
202 let event = OrderModifyRejected::new(
203 self.trader_id,
204 order.strategy_id(),
205 order.instrument_id(),
206 order.client_order_id(),
207 reason.into(),
208 UUID4::new(),
209 ts_event,
210 ts_init,
211 false,
212 venue_order_id,
213 Some(self.account_id),
214 );
215 OrderEventAny::ModifyRejected(event)
216 }
217
218 #[must_use]
220 pub fn generate_order_cancel_rejected(
221 &self,
222 order: &OrderAny,
223 venue_order_id: Option<VenueOrderId>,
224 reason: &str,
225 ts_event: UnixNanos,
226 ts_init: UnixNanos,
227 ) -> OrderEventAny {
228 let event = OrderCancelRejected::new(
229 self.trader_id,
230 order.strategy_id(),
231 order.instrument_id(),
232 order.client_order_id(),
233 reason.into(),
234 UUID4::new(),
235 ts_event,
236 ts_init,
237 false,
238 venue_order_id,
239 Some(self.account_id),
240 );
241 OrderEventAny::CancelRejected(event)
242 }
243
244 #[expect(clippy::too_many_arguments)]
246 #[must_use]
247 pub fn generate_order_updated(
248 &self,
249 order: &OrderAny,
250 venue_order_id: VenueOrderId,
251 quantity: Quantity,
252 price: Option<Price>,
253 trigger_price: Option<Price>,
254 protection_price: Option<Price>,
255 ts_event: UnixNanos,
256 ts_init: UnixNanos,
257 ) -> OrderEventAny {
258 let event = OrderUpdated::new(
259 self.trader_id,
260 order.strategy_id(),
261 order.instrument_id(),
262 order.client_order_id(),
263 quantity,
264 UUID4::new(),
265 ts_event,
266 ts_init,
267 false,
268 Some(venue_order_id),
269 Some(self.account_id),
270 price,
271 trigger_price,
272 protection_price,
273 false, );
275 OrderEventAny::Updated(event)
276 }
277
278 #[must_use]
280 pub fn generate_order_canceled(
281 &self,
282 order: &OrderAny,
283 venue_order_id: Option<VenueOrderId>,
284 ts_event: UnixNanos,
285 ts_init: UnixNanos,
286 ) -> OrderEventAny {
287 let event = OrderCanceled::new(
288 self.trader_id,
289 order.strategy_id(),
290 order.instrument_id(),
291 order.client_order_id(),
292 UUID4::new(),
293 ts_event,
294 ts_init,
295 false,
296 venue_order_id,
297 Some(self.account_id),
298 );
299 OrderEventAny::Canceled(event)
300 }
301
302 #[must_use]
304 pub fn generate_order_triggered(
305 &self,
306 order: &OrderAny,
307 venue_order_id: Option<VenueOrderId>,
308 ts_event: UnixNanos,
309 ts_init: UnixNanos,
310 ) -> OrderEventAny {
311 let event = OrderTriggered::new(
312 self.trader_id,
313 order.strategy_id(),
314 order.instrument_id(),
315 order.client_order_id(),
316 UUID4::new(),
317 ts_event,
318 ts_init,
319 false,
320 venue_order_id,
321 Some(self.account_id),
322 );
323 OrderEventAny::Triggered(event)
324 }
325
326 #[must_use]
328 pub fn generate_order_expired(
329 &self,
330 order: &OrderAny,
331 venue_order_id: Option<VenueOrderId>,
332 ts_event: UnixNanos,
333 ts_init: UnixNanos,
334 ) -> OrderEventAny {
335 let event = OrderExpired::new(
336 self.trader_id,
337 order.strategy_id(),
338 order.instrument_id(),
339 order.client_order_id(),
340 UUID4::new(),
341 ts_event,
342 ts_init,
343 false,
344 venue_order_id,
345 Some(self.account_id),
346 );
347 OrderEventAny::Expired(event)
348 }
349
350 #[expect(clippy::too_many_arguments)]
352 #[must_use]
353 pub fn generate_order_filled(
354 &self,
355 order: &OrderAny,
356 venue_order_id: VenueOrderId,
357 venue_position_id: Option<PositionId>,
358 trade_id: TradeId,
359 last_qty: Quantity,
360 last_px: Price,
361 quote_currency: Currency,
362 commission: Option<Money>,
363 liquidity_side: LiquiditySide,
364 ts_event: UnixNanos,
365 ts_init: UnixNanos,
366 ) -> OrderEventAny {
367 let event = OrderFilled::new(
368 self.trader_id,
369 order.strategy_id(),
370 order.instrument_id(),
371 order.client_order_id(),
372 venue_order_id,
373 self.account_id,
374 trade_id,
375 order.order_side(),
376 order.order_type(),
377 last_qty,
378 last_px,
379 quote_currency,
380 liquidity_side,
381 UUID4::new(),
382 ts_event,
383 ts_init,
384 false,
385 venue_position_id,
386 commission,
387 );
388 OrderEventAny::Filled(event)
389 }
390}