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