1use crate::matcher::Matcher;
2use crate::types::{FillEvent, MarketState, Order, OrderState, Side};
3
4pub struct SimpleMatcher {
5 orders: Vec<Order>,
6}
7
8impl Default for SimpleMatcher {
9 fn default() -> Self {
10 Self::new()
11 }
12}
13
14impl SimpleMatcher {
15 pub fn new() -> Self {
16 Self { orders: Vec::new() }
17 }
18}
19
20impl Matcher for SimpleMatcher {
21 fn add_order(&mut self, order: Order) {
22 self.orders.push(order);
23 }
24
25 fn cancel_order(&mut self, order_id: u64) {
26 if let Some(order) = self.orders.iter_mut().find(|o| o.id == order_id) {
27 order.state = OrderState::Cancelled;
28 }
29 self.orders.retain(|o| o.state == OrderState::Open);
30 }
31
32 fn cancel_all(&mut self) {
33 self.orders.clear();
34 }
35
36 fn process_quote(&mut self, state: &MarketState) -> Vec<FillEvent> {
37 let mut fills = Vec::new();
38 let timestamp = state.timestamp;
39
40 let best_ask = state.best_ask;
41 let best_bid = state.best_bid;
42
43 for order in self.orders.iter_mut() {
44 if order.state != OrderState::Open {
45 continue;
46 }
47
48 let mut filled = false;
49 let mut fill_price = 0.0;
50
51 match order.side {
52 Side::Buy => {
53 if order.limit_price >= best_ask {
55 filled = true;
56 fill_price = best_ask;
57 }
58 }
59 Side::Sell => {
60 if order.limit_price <= best_bid {
62 filled = true;
63 fill_price = best_bid;
64 }
65 }
66 }
67
68 if filled {
69 order.state = OrderState::Filled;
70 fills.push(FillEvent {
71 order_id: order.id,
72 timestamp, price: fill_price,
74 quantity: order.quantity,
75 side: order.side,
76 });
77 }
78 }
79
80 self.orders.retain(|o| o.state == OrderState::Open);
81
82 fills
83 }
84
85 fn get_orders(&self) -> &Vec<Order> {
86 &self.orders
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use crate::types::Side;
94
95 fn state(bid: f64, ask: f64) -> MarketState {
96 MarketState {
97 timestamp: 0.0,
98 best_bid: bid,
99 best_ask: ask,
100 last_price: None,
101 true_volatility: None,
102 true_drift: None,
103 parameters: None,
104 }
105 }
106
107 #[test]
108 fn test_buy_above_ask_fills_at_ask() {
109 let mut m = SimpleMatcher::new();
111 m.add_order(Order::new(1, Side::Buy, 101.0, 1.0));
112 let fills = m.process_quote(&state(99.0, 100.0));
113 assert_eq!(fills.len(), 1);
114 assert_eq!(fills[0].price, 100.0);
115 }
116
117 #[test]
118 fn test_buy_below_ask_does_not_fill() {
119 let mut m = SimpleMatcher::new();
121 m.add_order(Order::new(1, Side::Buy, 99.0, 1.0));
122 let fills = m.process_quote(&state(99.0, 100.0));
123 assert_eq!(fills.len(), 0);
124 }
125
126 #[test]
127 fn test_sell_at_or_below_bid_fills_at_bid() {
128 let mut m = SimpleMatcher::new();
130 m.add_order(Order::new(1, Side::Sell, 98.5, 2.0));
131 let fills = m.process_quote(&state(99.0, 100.0));
132 assert_eq!(fills.len(), 1);
133 assert_eq!(fills[0].price, 99.0);
134 assert_eq!(fills[0].quantity, 2.0);
135 }
136
137 #[test]
138 fn test_sell_above_bid_does_not_fill() {
139 let mut m = SimpleMatcher::new();
141 m.add_order(Order::new(1, Side::Sell, 100.5, 1.0));
142 let fills = m.process_quote(&state(99.0, 100.0));
143 assert_eq!(fills.len(), 0);
144 }
145
146 #[test]
147 fn test_multiple_bids_only_aggressive_fills() {
148 let mut m = SimpleMatcher::new();
150 m.add_order(Order::new(1, Side::Buy, 101.0, 1.0)); m.add_order(Order::new(2, Side::Buy, 99.0, 1.0)); let fills = m.process_quote(&state(99.5, 100.0));
153 assert_eq!(fills.len(), 1);
154 assert_eq!(fills[0].order_id, 1);
155 }
156
157 #[test]
158 fn test_multiple_bids_both_aggressive_fill_independently() {
159 let mut m = SimpleMatcher::new();
161 m.add_order(Order::new(1, Side::Buy, 101.0, 1.0));
162 m.add_order(Order::new(2, Side::Buy, 102.0, 2.0));
163 let fills = m.process_quote(&state(99.5, 100.0));
164 assert_eq!(fills.len(), 2);
165 for f in &fills {
166 assert_eq!(f.price, 100.0);
167 }
168 }
169
170 #[test]
171 fn test_cancel_order_prevents_fill() {
172 let mut m = SimpleMatcher::new();
174 m.add_order(Order::new(1, Side::Buy, 101.0, 1.0));
175 m.cancel_order(1);
176 let fills = m.process_quote(&state(99.0, 100.0));
177 assert_eq!(fills.len(), 0);
178 }
179
180 #[test]
181 fn test_cancel_nonexistent_order_is_noop() {
182 let mut m = SimpleMatcher::new();
184 m.add_order(Order::new(1, Side::Buy, 101.0, 1.0));
185 m.cancel_order(999);
186 let fills = m.process_quote(&state(99.0, 100.0));
187 assert_eq!(fills.len(), 1);
188 }
189
190 #[test]
191 fn test_filled_order_removed_from_book() {
192 let mut m = SimpleMatcher::new();
195 m.add_order(Order::new(1, Side::Buy, 101.0, 1.0));
196 let fills1 = m.process_quote(&state(99.0, 100.0));
197 assert_eq!(fills1.len(), 1);
198 let fills2 = m.process_quote(&state(99.0, 100.0));
200 assert_eq!(fills2.len(), 0);
201 }
202}