use nautilus_core::{UUID4, UnixNanos};
use crate::{
events::OrderAccepted,
identifiers::{AccountId, ClientOrderId, InstrumentId, StrategyId, TraderId, VenueOrderId},
stubs::{TestDefault, test_uuid},
};
#[derive(Debug, Clone, bon::Builder)]
#[builder(finish_fn = into_spec)]
pub struct OrderAcceptedSpec {
#[builder(default = TraderId::test_default())]
pub trader_id: TraderId,
#[builder(default = StrategyId::test_default())]
pub strategy_id: StrategyId,
#[builder(default = InstrumentId::test_default())]
pub instrument_id: InstrumentId,
#[builder(default = ClientOrderId::test_default())]
pub client_order_id: ClientOrderId,
#[builder(default = VenueOrderId::test_default())]
pub venue_order_id: VenueOrderId,
#[builder(default = AccountId::test_default())]
pub account_id: AccountId,
#[builder(default = test_uuid())]
pub event_id: UUID4,
#[builder(default = UnixNanos::default())]
pub ts_event: UnixNanos,
#[builder(default = UnixNanos::default())]
pub ts_init: UnixNanos,
#[builder(default = false)]
pub reconciliation: bool,
}
impl<S: order_accepted_spec_builder::IsComplete> OrderAcceptedSpecBuilder<S> {
#[must_use]
pub fn build(self) -> OrderAccepted {
let spec = self.into_spec();
OrderAccepted::new(
spec.trader_id,
spec.strategy_id,
spec.instrument_id,
spec.client_order_id,
spec.venue_order_id,
spec.account_id,
spec.event_id,
spec.ts_event,
spec.ts_init,
spec.reconciliation,
)
}
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use super::*;
use crate::stubs::reset_test_uuid_rng;
#[rstest]
fn defaults_are_sensible() {
let event = OrderAcceptedSpec::builder().build();
assert_eq!(event.trader_id, TraderId::test_default());
assert_eq!(event.strategy_id, StrategyId::test_default());
assert_eq!(event.instrument_id, InstrumentId::test_default());
assert_eq!(event.client_order_id, ClientOrderId::test_default());
assert_eq!(event.venue_order_id, VenueOrderId::test_default());
assert_eq!(event.account_id, AccountId::test_default());
assert_eq!(event.ts_event, UnixNanos::default());
assert_eq!(event.ts_init, UnixNanos::default());
assert_eq!(event.reconciliation, 0);
}
#[rstest]
fn overrides_apply_through_constructor() {
let event = OrderAcceptedSpec::builder()
.venue_order_id(VenueOrderId::from("V-1"))
.reconciliation(true)
.build();
assert_eq!(event.venue_order_id, VenueOrderId::from("V-1"));
assert_eq!(event.reconciliation, 1);
assert_eq!(event.trader_id, TraderId::test_default());
}
#[rstest]
fn event_ids_are_unique_within_a_run() {
reset_test_uuid_rng();
let a = OrderAcceptedSpec::builder().build();
let b = OrderAcceptedSpec::builder().build();
let c = OrderAcceptedSpec::builder().build();
assert_ne!(a.event_id, b.event_id);
assert_ne!(b.event_id, c.event_id);
assert_ne!(a.event_id, c.event_id);
}
#[rstest]
fn event_id_sequence_is_reproducible() {
reset_test_uuid_rng();
let first_run: Vec<_> = (0..3)
.map(|_| OrderAcceptedSpec::builder().build().event_id)
.collect();
reset_test_uuid_rng();
let second_run: Vec<_> = (0..3)
.map(|_| OrderAcceptedSpec::builder().build().event_id)
.collect();
assert_eq!(first_run, second_run);
}
}