1use std::collections::BTreeMap;
2use tracing::instrument;
3use uuid::Uuid;
4
5use crate::order_book::types::{BookDepth, CancelOrder, ModifyOrder, ModifyOutcome, OrderNode, PriceLevel, PriceLevelDepth};
6
7#[derive(Debug)]
8pub struct OrderBook{
9 pub security_id : u32,
10 pub ask : HalfBook,
11 pub bid : HalfBook
12}
13impl OrderBook {
14 pub fn new (security_id : u32,) -> Self{
15 Self { security_id , ask : HalfBook::new(), bid : HalfBook::new() }
16 }
17
18 #[instrument( name = "create_buy_order",
20 skip(self),
21 fields(
22 order_id = %order_id,
23 price = resting_order.market_limit
24 ),
25 err
26 )]
27 pub fn create_buy_order(&mut self, order_id : Uuid, resting_order : OrderNode) -> Result<usize, anyhow::Error>{
28
29 let mut order = resting_order;
30 let order_quantity = order.current_quantity;
31 let price = order.market_limit;
32
33 if let Some(price_level) = self.bid.price_map.get_mut(&price){
34 order.prev = price_level.tail;
35 if let Some(free_index) = self.bid.free_list.pop(){
36 self.bid.order_pool.insert(free_index, Some(order));
37 let prev_tail_idx = price_level.tail.unwrap();
38 price_level.tail = Some(free_index);
39 price_level.total_quantity += order_quantity;
40 price_level.order_count += 1;
41 if let Some(prev_order) = self.bid.order_pool.get_mut(prev_tail_idx).unwrap(){
42 prev_order.next = Some(free_index);
43 };
44 return Ok(free_index);
45 }
46 else {
47 self.bid.order_pool.push(Some(order));
48 let new_tail = self.bid.order_pool.len() - 1;
49 let pre_tail_idx = price_level.tail.unwrap();
50 price_level.tail = Some(new_tail);
51 price_level.total_quantity += order_quantity;
52 price_level.order_count += 1;
53 if let Some(prev_order) = self.bid.order_pool.get_mut(pre_tail_idx).unwrap(){
54 prev_order.next = Some(new_tail);
55 };
56 return Ok(new_tail);
57 }
58 }
59
60 let mut new_price_level = PriceLevel{
61 head : None,
62 tail : None,
63 order_count : 0,
64 total_quantity : 0
65 };
66 if let Some(free_index) = self.bid.free_list.pop(){
67 self.bid.order_pool.insert(free_index, Some(order));
68 new_price_level.head = Some(free_index);
69 new_price_level.tail = Some(free_index);
70 new_price_level.order_count += 1;
71 new_price_level.total_quantity += order_quantity;
72 self.bid.price_map.entry(price).or_insert(new_price_level);
73 return Ok(free_index)
74 }
75 self.bid.order_pool.push(Some(order));
76 let new_index = self.bid.order_pool.len()-1;
77 new_price_level.head = Some(new_index);
78 new_price_level.tail = Some(new_index);
79 new_price_level.order_count += 1;
80 new_price_level.total_quantity += order_quantity;
81 self.bid.price_map.entry(price).or_insert(new_price_level);
82
83 Ok(new_index)
84 }
85
86 #[instrument(
87 name = "create_sell_order",
88 skip(self),
89 fields(
90 order_id = %order_id,
91 price = resting_order.market_limit
92 ),
93 err
94 )]
95 pub fn create_sell_order(&mut self, order_id : Uuid, resting_order : OrderNode) -> Result<usize, anyhow::Error>{
96 let mut order = resting_order;
97 let order_quantity = order.current_quantity;
98 let price = order.market_limit;
99
100 if let Some(price_level) = self.ask.price_map.get_mut(&price){
101 order.prev = price_level.tail;
102 if let Some(free_index) = self.ask.free_list.pop(){
103 self.ask.order_pool.insert(free_index, Some(order));
104 let prev_tail_idx = price_level.tail.unwrap();
105 price_level.tail = Some(free_index);
106 price_level.total_quantity += order_quantity;
107 price_level.order_count += 1;
108 if let Some(prev_order) = self.ask.order_pool.get_mut(prev_tail_idx).unwrap(){
109 prev_order.next = Some(free_index);
110 };
111 return Ok(free_index);
112 }
113 else {
114 self.ask.order_pool.push(Some(order));
115 let new_tail = self.ask.order_pool.len() - 1;
116 let prev_tail_idx = price_level.tail.unwrap();
117 price_level.tail = Some(new_tail);
118 price_level.total_quantity += order_quantity;
119 price_level.order_count += 1;
120 if let Some(prev_order) = self.ask.order_pool.get_mut(prev_tail_idx).unwrap(){
121 prev_order.next = Some(new_tail);
122 };
123 return Ok(new_tail);
124 }
125 }
126
127 let mut new_price_level = PriceLevel{
128 head : None,
129 tail : None,
130 order_count : 0,
131 total_quantity : 0
132 };
133 if let Some(free_index) = self.ask.free_list.pop(){
134 self.ask.order_pool.insert(free_index, Some(order));
135 new_price_level.head = Some(free_index);
136 new_price_level.tail = Some(free_index);
137 new_price_level.order_count += 1;
138 new_price_level.total_quantity += order_quantity;
139 self.ask.price_map.entry(price).or_insert(new_price_level);
140 return Ok(free_index)
141 }
142 self.ask.order_pool.push(Some(order));
143 let new_index = self.ask.order_pool.len()-1;
144 new_price_level.head = Some(new_index);
145 new_price_level.tail = Some(new_index);
146 new_price_level.order_count += 1;
147 new_price_level.total_quantity += order_quantity;
148 self.ask.price_map.entry(price).or_insert(new_price_level);
149
150 Ok(new_index)
151 }
152
153 #[instrument(
154 name = "cancel_order",
155 skip(self),
156 fields(
157 order_id = %order_id
158 ),
159 err
160 )]
161 pub fn cancel_order(&mut self, order_id : Uuid, order : CancelOrder) -> Result<(), anyhow::Error>{
162 if order.is_buy_side {
163 let (prev, next) = {
164 let node = self.bid.order_pool[order.order_index].as_ref().unwrap();
165 (node.prev, node.next)
166 };
167 if let Some(prev_index) = prev{
168 if let Some(possible_prev_node) = self.bid.order_pool.get_mut(prev_index){
169 if let Some(prev_node) = possible_prev_node{
170 prev_node.next = next
171 }
172 }
173 }
174 if let Some(next_index) = next{
175 if let Some(possible_next_node) = self.bid.order_pool.get_mut(next_index){
176 if let Some(next_node) = possible_next_node{
177 next_node.prev = prev
178 }
179 }
180 }
181 self.bid.order_pool.insert(order.order_index, None);
182 self.bid.free_list.push(order.order_index);
183
184 } else {
185 let (prev, next) = {
186 let node = self.ask.order_pool[order.order_index].as_ref().unwrap();
187 (node.prev, node.next)
188 };
189 if let Some(prev_index) = prev{
190 if let Some(possible_prev_node) = self.ask.order_pool.get_mut(prev_index){
191 if let Some(prev_node) = possible_prev_node{
192 prev_node.next = next
193 }
194 }
195 }
196 if let Some(next_index) = next{
197 if let Some(possible_next_node) = self.ask.order_pool.get_mut(next_index){
198 if let Some(next_node) = possible_next_node{
199 next_node.prev = prev
200 }
201 }
202 }
203 self.ask.order_pool.insert(order.order_index, None);
204 self.ask.free_list.push(order.order_index);
205 }
206 Ok(())
207 }
208
209 #[instrument(
210 name = "modify_order",
211 skip(self),
212 fields(
213 order_id = %order_id,
214 ),
215 err
216 )]
217 pub fn modify_order(&mut self, order_id : Uuid, order : ModifyOrder) -> Result<Option<ModifyOutcome>, anyhow::Error>{
218 if order.is_buy_side{
219 let (old_initial_qty, old_current_qty, old_price) = {
220 let node = self.bid.order_pool[order.order_index].as_ref().unwrap();
221 (node.initial_quantity, node.current_quantity, node.market_limit)
222 };
223 if let Some(new_price) = order.new_price && let Some(new_qty) = order.new_quantity{
224 if new_price != old_price{
225 if let Ok(_) = self.cancel_order(order_id ,CancelOrder { order_index : order.order_index, is_buy_side: order.is_buy_side,}){
226 return Ok(Some(ModifyOutcome::Both {new_price, new_initial_qty: new_qty, old_current_qty }));
227 }
228 }
229 return Ok(None);
230 } else if let Some(new_qty) = order.new_quantity {
231 if new_qty > old_initial_qty{
232 if let Ok(_) = self.cancel_order(order_id ,CancelOrder { order_index : order.order_index, is_buy_side: order.is_buy_side,}){
233 return Ok(Some(ModifyOutcome::Requantized {old_price, new_initial_qty: new_qty, old_current_qty }))
234 }
235 return Ok(None);
236 }
237 else {
238 let order_node = self.bid.order_pool[order.order_index].as_mut().unwrap();
239 order_node.initial_quantity = new_qty;
240 return Ok(Some(ModifyOutcome::Inplace));
241 }
242 } else {
243 if let Ok(_) = self.cancel_order(order_id ,CancelOrder { order_index : order.order_index, is_buy_side: order.is_buy_side,}){
244 return Ok(Some(ModifyOutcome::Repriced {new_price : order.new_price.unwrap(), old_initial_qty, old_current_qty }));
245 }
246 return Ok(None);
247 }
248 } else {
249 let (old_initial_qty, old_current_qty, old_price) = {
250 let node = self.ask.order_pool[order.order_index].as_ref().unwrap();
251 (node.initial_quantity, node.current_quantity, node.market_limit)
252 };
253
254 if let Some(new_price) = order.new_price && let Some(new_qty) = order.new_quantity{
255 if new_price != old_price{
256 if let Ok(_) = self.cancel_order(order_id ,CancelOrder { order_index : order.order_index, is_buy_side: order.is_buy_side,}){
257 return Ok(Some(ModifyOutcome::Requantized {old_price, new_initial_qty: new_qty, old_current_qty }))
258 }
259 }
260 return Ok(None);
261 } else if let Some(new_qty) = order.new_quantity {
262 if new_qty > old_initial_qty{
263 if let Ok(_) = self.cancel_order(order_id ,CancelOrder { order_index : order.order_index, is_buy_side: order.is_buy_side,}){
264 return Ok(Some(ModifyOutcome::Requantized { old_price, new_initial_qty: new_qty, old_current_qty }))
265 }
266 return Ok(None);
267 }
268 else {
269 let order_node = self.ask.order_pool[order.order_index].as_mut().unwrap();
270 order_node.initial_quantity = new_qty;
271 return Ok(Some(ModifyOutcome::Inplace));
272 }
273 }else {
274 if let Ok(_) = self.cancel_order(order_id ,CancelOrder { order_index : order.order_index, is_buy_side: order.is_buy_side,}){
275 return Ok(Some(ModifyOutcome::Repriced { new_price : order.new_price.unwrap(), old_initial_qty, old_current_qty }));
276 }
277 return Ok(None);
278 }
279 }
280 }
281
282 #[instrument(
283 name = "book_depth",
284 skip(self),
285 err
286 )]
287 pub fn depth(&self, levels_count : Option<u32>) -> Result<BookDepth, anyhow::Error>{
288
289 let ask_iter = self.ask.price_map.iter().rev();
290 let bid_iter = self.bid.price_map.iter();
291
292 let ask_depth : Vec<_> = match levels_count {
293 Some(n) => ask_iter.take(n as usize)
294 .map(|(price, price_level)| PriceLevelDepth {
295 price_level : *price,
296 quantity : price_level.total_quantity
297 })
298 .collect(),
299 None => ask_iter.map(|(price, price_level)| PriceLevelDepth {
300 price_level : *price,
301 quantity : price_level.total_quantity
302 }).collect()
303 };
304 let bid_depth = match levels_count {
305 Some(n) => bid_iter.take(n as usize)
306 .map(|(price, price_level)| PriceLevelDepth {
307 price_level : *price,
308 quantity : price_level.total_quantity
309 })
310 .collect(),
311 None => bid_iter.map(|(price, price_level)| PriceLevelDepth {
312 price_level : *price,
313 quantity : price_level.total_quantity
314 }).collect()
315 };
316 Ok(BookDepth { bid_depth, ask_depth })
317 }
318}
319
320#[derive(Debug)]
321pub struct HalfBook{
322 pub price_map : BTreeMap<u32, PriceLevel>,
323 pub order_pool : Vec<Option<OrderNode>>,
324 pub free_list : Vec<usize>, }
326
327impl HalfBook {
328 pub fn new() -> Self{
329 Self { price_map: BTreeMap::new(), order_pool: Vec::new(), free_list: Vec::new()}
330 }
331}