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 #[allow(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 );
269 OrderEventAny::Updated(event)
270 }
271
272 #[must_use]
274 pub fn generate_order_canceled(
275 &self,
276 order: &OrderAny,
277 venue_order_id: Option<VenueOrderId>,
278 ts_event: UnixNanos,
279 ts_init: UnixNanos,
280 ) -> OrderEventAny {
281 let event = OrderCanceled::new(
282 self.trader_id,
283 order.strategy_id(),
284 order.instrument_id(),
285 order.client_order_id(),
286 UUID4::new(),
287 ts_event,
288 ts_init,
289 false,
290 venue_order_id,
291 Some(self.account_id),
292 );
293 OrderEventAny::Canceled(event)
294 }
295
296 #[must_use]
298 pub fn generate_order_triggered(
299 &self,
300 order: &OrderAny,
301 venue_order_id: Option<VenueOrderId>,
302 ts_event: UnixNanos,
303 ts_init: UnixNanos,
304 ) -> OrderEventAny {
305 let event = OrderTriggered::new(
306 self.trader_id,
307 order.strategy_id(),
308 order.instrument_id(),
309 order.client_order_id(),
310 UUID4::new(),
311 ts_event,
312 ts_init,
313 false,
314 venue_order_id,
315 Some(self.account_id),
316 );
317 OrderEventAny::Triggered(event)
318 }
319
320 #[must_use]
322 pub fn generate_order_expired(
323 &self,
324 order: &OrderAny,
325 venue_order_id: Option<VenueOrderId>,
326 ts_event: UnixNanos,
327 ts_init: UnixNanos,
328 ) -> OrderEventAny {
329 let event = OrderExpired::new(
330 self.trader_id,
331 order.strategy_id(),
332 order.instrument_id(),
333 order.client_order_id(),
334 UUID4::new(),
335 ts_event,
336 ts_init,
337 false,
338 venue_order_id,
339 Some(self.account_id),
340 );
341 OrderEventAny::Expired(event)
342 }
343
344 #[allow(clippy::too_many_arguments)]
346 #[must_use]
347 pub fn generate_order_filled(
348 &self,
349 order: &OrderAny,
350 venue_order_id: VenueOrderId,
351 venue_position_id: Option<PositionId>,
352 trade_id: TradeId,
353 last_qty: Quantity,
354 last_px: Price,
355 quote_currency: Currency,
356 commission: Option<Money>,
357 liquidity_side: LiquiditySide,
358 ts_event: UnixNanos,
359 ts_init: UnixNanos,
360 ) -> OrderEventAny {
361 let event = OrderFilled::new(
362 self.trader_id,
363 order.strategy_id(),
364 order.instrument_id(),
365 order.client_order_id(),
366 venue_order_id,
367 self.account_id,
368 trade_id,
369 order.order_side(),
370 order.order_type(),
371 last_qty,
372 last_px,
373 quote_currency,
374 liquidity_side,
375 UUID4::new(),
376 ts_event,
377 ts_init,
378 false,
379 venue_position_id,
380 commission,
381 );
382 OrderEventAny::Filled(event)
383 }
384}