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 #[must_use]
75 pub fn generate_account_state(
76 &self,
77 balances: Vec<AccountBalance>,
78 margins: Vec<MarginBalance>,
79 reported: bool,
80 ts_event: UnixNanos,
81 ts_init: UnixNanos,
82 ) -> AccountState {
83 AccountState::new(
84 self.account_id,
85 self.account_type,
86 balances,
87 margins,
88 reported,
89 UUID4::new(),
90 ts_event,
91 ts_init,
92 self.base_currency,
93 )
94 }
95
96 #[must_use]
100 pub fn generate_order_denied(
101 &self,
102 order: &OrderAny,
103 reason: &str,
104 ts_init: UnixNanos,
105 ) -> OrderEventAny {
106 let event = OrderDenied::new(
107 self.trader_id,
108 order.strategy_id(),
109 order.instrument_id(),
110 order.client_order_id(),
111 reason.into(),
112 UUID4::new(),
113 ts_init,
114 ts_init,
115 );
116 OrderEventAny::Denied(event)
117 }
118
119 #[must_use]
123 pub fn generate_order_submitted(&self, order: &OrderAny, ts_init: UnixNanos) -> OrderEventAny {
124 let event = OrderSubmitted::new(
125 self.trader_id,
126 order.strategy_id(),
127 order.instrument_id(),
128 order.client_order_id(),
129 self.account_id,
130 UUID4::new(),
131 ts_init,
132 ts_init,
133 );
134 OrderEventAny::Submitted(event)
135 }
136
137 #[must_use]
139 pub fn generate_order_rejected(
140 &self,
141 order: &OrderAny,
142 reason: &str,
143 ts_event: UnixNanos,
144 ts_init: UnixNanos,
145 due_post_only: bool,
146 ) -> OrderEventAny {
147 let event = OrderRejected::new(
148 self.trader_id,
149 order.strategy_id(),
150 order.instrument_id(),
151 order.client_order_id(),
152 self.account_id,
153 reason.into(),
154 UUID4::new(),
155 ts_event,
156 ts_init,
157 false,
158 due_post_only,
159 );
160 OrderEventAny::Rejected(event)
161 }
162
163 #[must_use]
165 pub fn generate_order_accepted(
166 &self,
167 order: &OrderAny,
168 venue_order_id: VenueOrderId,
169 ts_event: UnixNanos,
170 ts_init: UnixNanos,
171 ) -> OrderEventAny {
172 let event = OrderAccepted::new(
173 self.trader_id,
174 order.strategy_id(),
175 order.instrument_id(),
176 order.client_order_id(),
177 venue_order_id,
178 self.account_id,
179 UUID4::new(),
180 ts_event,
181 ts_init,
182 false,
183 );
184 OrderEventAny::Accepted(event)
185 }
186
187 #[must_use]
189 pub fn generate_order_modify_rejected(
190 &self,
191 order: &OrderAny,
192 venue_order_id: Option<VenueOrderId>,
193 reason: &str,
194 ts_event: UnixNanos,
195 ts_init: UnixNanos,
196 ) -> OrderEventAny {
197 let event = OrderModifyRejected::new(
198 self.trader_id,
199 order.strategy_id(),
200 order.instrument_id(),
201 order.client_order_id(),
202 reason.into(),
203 UUID4::new(),
204 ts_event,
205 ts_init,
206 false,
207 venue_order_id,
208 Some(self.account_id),
209 );
210 OrderEventAny::ModifyRejected(event)
211 }
212
213 #[must_use]
215 pub fn generate_order_cancel_rejected(
216 &self,
217 order: &OrderAny,
218 venue_order_id: Option<VenueOrderId>,
219 reason: &str,
220 ts_event: UnixNanos,
221 ts_init: UnixNanos,
222 ) -> OrderEventAny {
223 let event = OrderCancelRejected::new(
224 self.trader_id,
225 order.strategy_id(),
226 order.instrument_id(),
227 order.client_order_id(),
228 reason.into(),
229 UUID4::new(),
230 ts_event,
231 ts_init,
232 false,
233 venue_order_id,
234 Some(self.account_id),
235 );
236 OrderEventAny::CancelRejected(event)
237 }
238
239 #[expect(clippy::too_many_arguments)]
241 #[must_use]
242 pub fn generate_order_updated(
243 &self,
244 order: &OrderAny,
245 venue_order_id: VenueOrderId,
246 quantity: Quantity,
247 price: Option<Price>,
248 trigger_price: Option<Price>,
249 protection_price: Option<Price>,
250 ts_event: UnixNanos,
251 ts_init: UnixNanos,
252 ) -> OrderEventAny {
253 let event = OrderUpdated::new(
254 self.trader_id,
255 order.strategy_id(),
256 order.instrument_id(),
257 order.client_order_id(),
258 quantity,
259 UUID4::new(),
260 ts_event,
261 ts_init,
262 false,
263 Some(venue_order_id),
264 Some(self.account_id),
265 price,
266 trigger_price,
267 protection_price,
268 false, );
270 OrderEventAny::Updated(event)
271 }
272
273 #[must_use]
275 pub fn generate_order_canceled(
276 &self,
277 order: &OrderAny,
278 venue_order_id: Option<VenueOrderId>,
279 ts_event: UnixNanos,
280 ts_init: UnixNanos,
281 ) -> OrderEventAny {
282 let event = OrderCanceled::new(
283 self.trader_id,
284 order.strategy_id(),
285 order.instrument_id(),
286 order.client_order_id(),
287 UUID4::new(),
288 ts_event,
289 ts_init,
290 false,
291 venue_order_id,
292 Some(self.account_id),
293 );
294 OrderEventAny::Canceled(event)
295 }
296
297 #[must_use]
299 pub fn generate_order_triggered(
300 &self,
301 order: &OrderAny,
302 venue_order_id: Option<VenueOrderId>,
303 ts_event: UnixNanos,
304 ts_init: UnixNanos,
305 ) -> OrderEventAny {
306 let event = OrderTriggered::new(
307 self.trader_id,
308 order.strategy_id(),
309 order.instrument_id(),
310 order.client_order_id(),
311 UUID4::new(),
312 ts_event,
313 ts_init,
314 false,
315 venue_order_id,
316 Some(self.account_id),
317 );
318 OrderEventAny::Triggered(event)
319 }
320
321 #[must_use]
323 pub fn generate_order_expired(
324 &self,
325 order: &OrderAny,
326 venue_order_id: Option<VenueOrderId>,
327 ts_event: UnixNanos,
328 ts_init: UnixNanos,
329 ) -> OrderEventAny {
330 let event = OrderExpired::new(
331 self.trader_id,
332 order.strategy_id(),
333 order.instrument_id(),
334 order.client_order_id(),
335 UUID4::new(),
336 ts_event,
337 ts_init,
338 false,
339 venue_order_id,
340 Some(self.account_id),
341 );
342 OrderEventAny::Expired(event)
343 }
344
345 #[expect(clippy::too_many_arguments)]
347 #[must_use]
348 pub fn generate_order_filled(
349 &self,
350 order: &OrderAny,
351 venue_order_id: VenueOrderId,
352 venue_position_id: Option<PositionId>,
353 trade_id: TradeId,
354 last_qty: Quantity,
355 last_px: Price,
356 quote_currency: Currency,
357 commission: Option<Money>,
358 liquidity_side: LiquiditySide,
359 ts_event: UnixNanos,
360 ts_init: UnixNanos,
361 ) -> OrderEventAny {
362 let event = OrderFilled::new(
363 self.trader_id,
364 order.strategy_id(),
365 order.instrument_id(),
366 order.client_order_id(),
367 venue_order_id,
368 self.account_id,
369 trade_id,
370 order.order_side(),
371 order.order_type(),
372 last_qty,
373 last_px,
374 quote_currency,
375 liquidity_side,
376 UUID4::new(),
377 ts_event,
378 ts_init,
379 false,
380 venue_position_id,
381 commission,
382 );
383 OrderEventAny::Filled(event)
384 }
385}