nautilus_execution/order_manager/
handlers.rs1use nautilus_common::messages::execution::SubmitOrder;
22use nautilus_core::WeakCell;
23use nautilus_model::{orders::OrderAny, types::Quantity};
24
25use crate::order_emulator::emulator::OrderEmulator;
26
27pub trait SubmitOrderHandler {
28 fn handle_submit_order(&self, command: SubmitOrder);
29}
30
31#[derive(Clone, Debug)]
33pub enum SubmitOrderHandlerAny {
34 OrderEmulator(WeakCell<OrderEmulator>),
35}
36
37impl SubmitOrderHandler for SubmitOrderHandlerAny {
38 fn handle_submit_order(&self, command: SubmitOrder) {
39 match self {
40 Self::OrderEmulator(emulator_weak) => {
41 if let Some(emulator) = emulator_weak.upgrade() {
42 emulator.borrow_mut().handle_submit_order(command);
43 }
44 }
45 }
46 }
47}
48
49pub trait CancelOrderHandler {
50 fn handle_cancel_order(&self, order: &OrderAny);
51}
52
53#[derive(Clone, Debug)]
55pub enum CancelOrderHandlerAny {
56 OrderEmulator(WeakCell<OrderEmulator>),
57}
58
59impl CancelOrderHandler for CancelOrderHandlerAny {
60 fn handle_cancel_order(&self, order: &OrderAny) {
61 match self {
62 Self::OrderEmulator(emulator_weak) => {
63 if let Some(emulator) = emulator_weak.upgrade() {
64 emulator.borrow_mut().cancel_order(order);
65 }
66 }
67 }
68 }
69}
70
71pub trait ModifyOrderHandler {
72 fn handle_modify_order(&self, order: &OrderAny, new_quantity: Quantity);
73}
74
75#[derive(Clone, Debug)]
77pub enum ModifyOrderHandlerAny {
78 OrderEmulator(WeakCell<OrderEmulator>),
79}
80
81impl ModifyOrderHandler for ModifyOrderHandlerAny {
82 fn handle_modify_order(&self, order: &OrderAny, new_quantity: Quantity) {
83 match self {
84 Self::OrderEmulator(emulator_weak) => {
85 if let Some(emulator) = emulator_weak.upgrade() {
86 let mut order_clone = order.clone();
87 emulator
88 .borrow_mut()
89 .update_order(&mut order_clone, new_quantity);
90 }
91 }
92 }
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use std::{cell::RefCell, rc::Rc};
99
100 use nautilus_common::{cache::Cache, clock::TestClock};
101 use nautilus_core::{UUID4, WeakCell};
102 use nautilus_model::{
103 enums::{OrderSide, OrderType, TriggerType},
104 identifiers::{StrategyId, TraderId},
105 instruments::{Instrument, stubs::audusd_sim},
106 orders::{Order, OrderTestBuilder},
107 types::{Price, Quantity},
108 };
109 use rstest::rstest;
110
111 use super::*;
112 use crate::order_emulator::emulator::OrderEmulator;
113
114 fn create_test_emulator() -> Rc<RefCell<OrderEmulator>> {
115 let clock = Rc::new(RefCell::new(TestClock::new()));
116 let cache = Rc::new(RefCell::new(Cache::new(None, None)));
117
118 Rc::new(RefCell::new(OrderEmulator::new(clock, cache)))
119 }
120
121 fn create_test_stop_order(instrument: &dyn Instrument) -> OrderAny {
122 OrderTestBuilder::new(OrderType::StopMarket)
123 .instrument_id(instrument.id())
124 .side(OrderSide::Buy)
125 .trigger_price(Price::from("1.00050"))
126 .quantity(Quantity::from(100_000))
127 .emulation_trigger(TriggerType::BidAsk)
128 .build()
129 }
130
131 #[rstest]
132 fn test_submit_order_handler_constructs() {
133 let emulator = create_test_emulator();
134 let weak_emulator = WeakCell::from(Rc::downgrade(&emulator));
135 let handler = SubmitOrderHandlerAny::OrderEmulator(weak_emulator);
136
137 assert!(matches!(handler, SubmitOrderHandlerAny::OrderEmulator(_)));
138 }
139
140 #[rstest]
141 fn test_cancel_order_handler_constructs() {
142 let emulator = create_test_emulator();
143 let weak_emulator = WeakCell::from(Rc::downgrade(&emulator));
144 let handler = CancelOrderHandlerAny::OrderEmulator(weak_emulator);
145
146 assert!(matches!(handler, CancelOrderHandlerAny::OrderEmulator(_)));
147 }
148
149 #[rstest]
150 fn test_modify_order_handler_constructs() {
151 let emulator = create_test_emulator();
152 let weak_emulator = WeakCell::from(Rc::downgrade(&emulator));
153 let handler = ModifyOrderHandlerAny::OrderEmulator(weak_emulator);
154
155 assert!(matches!(handler, ModifyOrderHandlerAny::OrderEmulator(_)));
156 }
157
158 #[rstest]
159 fn test_cancel_order_handler_dispatch_does_not_panic() {
160 let emulator = create_test_emulator();
161 let weak_emulator = WeakCell::from(Rc::downgrade(&emulator));
162 let handler = CancelOrderHandlerAny::OrderEmulator(weak_emulator);
163 let instrument = audusd_sim();
164 let order = create_test_stop_order(&instrument);
165
166 handler.handle_cancel_order(&order);
167 }
168
169 #[rstest]
170 fn test_modify_order_handler_dispatch_does_not_panic() {
171 let emulator = create_test_emulator();
172 let weak_emulator = WeakCell::from(Rc::downgrade(&emulator));
173 let handler = ModifyOrderHandlerAny::OrderEmulator(weak_emulator);
174 let instrument = audusd_sim();
175 let order = create_test_stop_order(&instrument);
176 let new_quantity = Quantity::from(50_000);
177
178 handler.handle_modify_order(&order, new_quantity);
179 }
180
181 #[rstest]
182 fn test_handler_with_dropped_emulator_does_not_panic() {
183 let emulator = create_test_emulator();
184 let weak_emulator = WeakCell::from(Rc::downgrade(&emulator));
185 let handler = SubmitOrderHandlerAny::OrderEmulator(weak_emulator);
186 let instrument = audusd_sim();
187 let order = create_test_stop_order(&instrument);
188 let command = SubmitOrder::new(
189 TraderId::from("TESTER-001"),
190 None,
191 StrategyId::from("STRATEGY-001"),
192 instrument.id(),
193 order.client_order_id(),
194 order.init_event().clone(),
195 None,
196 None,
197 None,
198 UUID4::new(),
199 0.into(),
200 );
201 drop(emulator);
202
203 handler.handle_submit_order(command);
205 }
206}