nautilus_model/orders/
stubs.rs1use std::str::FromStr;
17
18use nautilus_core::{UnixNanos, UUID4};
19
20use super::any::OrderAny;
21use crate::{
22 enums::LiquiditySide,
23 events::{OrderAccepted, OrderEventAny, OrderFilled, OrderSubmitted},
24 identifiers::{AccountId, PositionId, TradeId, VenueOrderId},
25 instruments::InstrumentAny,
26 types::{Money, Price, Quantity},
27};
28
29pub struct TestOrderEventStubs;
31
32impl TestOrderEventStubs {
33 pub fn order_submitted(order: &OrderAny, account_id: AccountId) -> OrderEventAny {
34 let event = OrderSubmitted::new(
35 order.trader_id(),
36 order.strategy_id(),
37 order.instrument_id(),
38 order.client_order_id(),
39 account_id,
40 UUID4::new(),
41 UnixNanos::default(),
42 UnixNanos::default(),
43 );
44 OrderEventAny::Submitted(event)
45 }
46
47 pub fn order_accepted(
48 order: &OrderAny,
49 account_id: AccountId,
50 venue_order_id: VenueOrderId,
51 ) -> OrderEventAny {
52 let event = OrderAccepted::new(
53 order.trader_id(),
54 order.strategy_id(),
55 order.instrument_id(),
56 order.client_order_id(),
57 venue_order_id,
58 account_id,
59 UUID4::new(),
60 UnixNanos::default(),
61 UnixNanos::default(),
62 false,
63 );
64 OrderEventAny::Accepted(event)
65 }
66
67 #[allow(clippy::too_many_arguments)]
68 pub fn order_filled(
69 order: &OrderAny,
70 instrument: &InstrumentAny,
71 trade_id: Option<TradeId>,
72 position_id: Option<PositionId>,
73 last_px: Option<Price>,
74 last_qty: Option<Quantity>,
75 liquidity_side: Option<LiquiditySide>,
76 commission: Option<Money>,
77 ts_filled_ns: Option<UnixNanos>,
78 account_id: Option<AccountId>,
79 ) -> OrderEventAny {
80 let venue_order_id = order.venue_order_id().unwrap_or_default();
81 let account_id = account_id
82 .or(order.account_id())
83 .unwrap_or(AccountId::from("SIM-001"));
84 let trade_id = trade_id.unwrap_or(TradeId::new(
85 order.client_order_id().as_str().replace('O', "E").as_str(),
86 ));
87 let liquidity_side = liquidity_side.unwrap_or(LiquiditySide::Maker);
88 let event = UUID4::new();
89 let position_id = position_id
90 .or_else(|| order.position_id())
91 .unwrap_or(PositionId::new("1"));
92 let commission = commission.unwrap_or(Money::from("2 USD"));
93 let last_px = last_px.unwrap_or(Price::from_str("1.0").unwrap());
94 let last_qty = last_qty.unwrap_or(order.quantity());
95 let event = OrderFilled::new(
96 order.trader_id(),
97 order.strategy_id(),
98 instrument.id(),
99 order.client_order_id(),
100 venue_order_id,
101 account_id,
102 trade_id,
103 order.order_side(),
104 order.order_type(),
105 last_qty,
106 last_px,
107 instrument.quote_currency(),
108 liquidity_side,
109 event,
110 ts_filled_ns.unwrap_or_default(),
111 UnixNanos::default(),
112 false,
113 Some(position_id),
114 Some(commission),
115 );
116 OrderEventAny::Filled(event)
117 }
118}
119
120pub struct TestOrderStubs;
121
122impl TestOrderStubs {
123 pub fn make_accepted_order(order: &OrderAny) -> OrderAny {
124 let mut new_order = order.clone();
125 let submitted_event =
126 TestOrderEventStubs::order_submitted(&new_order, AccountId::from("SIM-001"));
127 let accepted_event = TestOrderEventStubs::order_accepted(
128 &new_order,
129 AccountId::from("SIM-001"),
130 VenueOrderId::from("V-001"),
131 );
132 new_order.apply(submitted_event).unwrap();
133 new_order.apply(accepted_event).unwrap();
134 new_order
135 }
136
137 pub fn make_filled_order(
138 order: &OrderAny,
139 instrument: &InstrumentAny,
140 liquidity_side: LiquiditySide,
141 ) -> OrderAny {
142 let mut accepted_order = TestOrderStubs::make_accepted_order(order);
143 let fill = TestOrderEventStubs::order_filled(
144 &accepted_order,
145 instrument,
146 None,
147 None,
148 None,
149 None,
150 Some(liquidity_side),
151 None,
152 None,
153 None,
154 );
155 accepted_order.apply(fill).unwrap();
156 accepted_order
157 }
158}