nautilus_model/events/order/spec/
pending_cancel.rs1use nautilus_core::{UUID4, UnixNanos};
17
18use crate::{
19 events::OrderPendingCancel,
20 identifiers::{AccountId, ClientOrderId, InstrumentId, StrategyId, TraderId, VenueOrderId},
21 stubs::{TestDefault, test_uuid},
22};
23
24#[derive(Debug, Clone, bon::Builder)]
30#[builder(finish_fn = into_spec)]
31pub struct OrderPendingCancelSpec {
32 #[builder(default = TraderId::test_default())]
33 pub trader_id: TraderId,
34 #[builder(default = StrategyId::test_default())]
35 pub strategy_id: StrategyId,
36 #[builder(default = InstrumentId::test_default())]
37 pub instrument_id: InstrumentId,
38 #[builder(default = ClientOrderId::test_default())]
39 pub client_order_id: ClientOrderId,
40 pub account_id: Option<AccountId>,
41 #[builder(default = test_uuid())]
42 pub event_id: UUID4,
43 #[builder(default = UnixNanos::default())]
44 pub ts_event: UnixNanos,
45 #[builder(default = UnixNanos::default())]
46 pub ts_init: UnixNanos,
47 #[builder(default = false)]
48 pub reconciliation: bool,
49 pub venue_order_id: Option<VenueOrderId>,
50}
51
52impl<S: order_pending_cancel_spec_builder::IsComplete> OrderPendingCancelSpecBuilder<S> {
53 #[must_use]
55 pub fn build(self) -> OrderPendingCancel {
56 let spec = self.into_spec();
57 OrderPendingCancel::new(
58 spec.trader_id,
59 spec.strategy_id,
60 spec.instrument_id,
61 spec.client_order_id,
62 spec.account_id,
63 spec.event_id,
64 spec.ts_event,
65 spec.ts_init,
66 spec.reconciliation,
67 spec.venue_order_id,
68 )
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use rstest::rstest;
75
76 use super::*;
77 use crate::stubs::reset_test_uuid_rng;
78
79 #[rstest]
80 fn defaults_are_sensible() {
81 let event = OrderPendingCancelSpec::builder().build();
84 assert_eq!(event.trader_id, TraderId::test_default());
85 assert_eq!(event.strategy_id, StrategyId::test_default());
86 assert_eq!(event.instrument_id, InstrumentId::test_default());
87 assert_eq!(event.client_order_id, ClientOrderId::test_default());
88 assert_eq!(event.account_id, None);
89 assert_eq!(event.ts_event, UnixNanos::default());
90 assert_eq!(event.ts_init, UnixNanos::default());
91 assert!(!event.reconciliation);
92 assert_eq!(event.venue_order_id, None);
93 }
94
95 #[rstest]
96 fn overrides_apply_through_constructor() {
97 let event = OrderPendingCancelSpec::builder()
98 .account_id(AccountId::from("SIM-002"))
99 .venue_order_id(VenueOrderId::from("V-1"))
100 .reconciliation(true)
101 .build();
102
103 assert_eq!(event.account_id, Some(AccountId::from("SIM-002")));
104 assert_eq!(event.venue_order_id, Some(VenueOrderId::from("V-1")));
105 assert!(event.reconciliation);
106 assert_eq!(event.trader_id, TraderId::test_default());
107 }
108
109 #[rstest]
110 fn accepts_an_absent_account_id() {
111 let event = OrderPendingCancelSpec::builder()
112 .maybe_account_id(None)
113 .build();
114
115 assert_eq!(event.account_id, None);
116 }
117
118 #[rstest]
119 fn event_ids_are_unique_within_a_run() {
120 reset_test_uuid_rng();
121 let a = OrderPendingCancelSpec::builder().build();
122 let b = OrderPendingCancelSpec::builder().build();
123 let c = OrderPendingCancelSpec::builder().build();
124 assert_ne!(a.event_id, b.event_id);
125 assert_ne!(b.event_id, c.event_id);
126 assert_ne!(a.event_id, c.event_id);
127 }
128
129 #[rstest]
130 fn event_id_sequence_is_reproducible() {
131 reset_test_uuid_rng();
133 let first_run: Vec<_> = (0..3)
134 .map(|_| OrderPendingCancelSpec::builder().build().event_id)
135 .collect();
136
137 reset_test_uuid_rng();
138 let second_run: Vec<_> = (0..3)
139 .map(|_| OrderPendingCancelSpec::builder().build().event_id)
140 .collect();
141
142 assert_eq!(first_run, second_run);
143 }
144}