1use std::{collections::{BTreeMap, HashMap, btree_map::Entry}, time::Instant};
2use anyhow::anyhow;
3use crate::order_book::types::{BookDepth, EngineCancelOrder, EngineModifyOrder, ModifyOutcome, OrderNode, PriceLevel, PriceLevelDepth};
4
5#[derive(Debug)]
6pub struct OrderBook{
7 pub ask : HalfBook,
8 pub bid : HalfBook
9}
10impl OrderBook {
11 pub fn new () -> Self{
12 Self { ask : HalfBook::new(), bid : HalfBook::new() }
13 }
14
15 pub fn create_buy_order(&mut self, resting_order : OrderNode) -> Result<usize, anyhow::Error>{
16
17 let mut order = resting_order;
18 let order_quantity = order.current_quantity;
19 let price = order.market_limit;
20 let order_id = resting_order.order_id;
21
22 match self.bid.price_map.entry(price){ Entry::Occupied(mut entry) => {
24 let price_level = entry.get_mut();
25 if price_level.total_quantity == 0 || price_level.head == None || price_level.tail == None{
26 entry.remove();
27 } else {
28 order.prev = price_level.tail;
29 if let Some(free_index) = self.bid.free_list.pop(){
30 self.bid.order_registry.insert(order_id, free_index);
31 self.bid.order_pool[free_index] = Some(order);
32 let prev_tail_idx = price_level.tail.unwrap();
33 price_level.tail = Some(free_index);
34 price_level.total_quantity += order_quantity;
35 price_level.order_count += 1;
36 if let Some(prev_order) = self.bid.order_pool.get_mut(prev_tail_idx).unwrap(){
37 prev_order.next = Some(free_index);
38 };
39 return Ok(free_index);
40 }
41 else {
42 self.bid.order_pool.push(Some(order));
43 let new_tail = self.bid.order_pool.len() - 1;
44 self.bid.order_registry.insert(order_id, new_tail);
45 let pre_tail_idx = price_level.tail.unwrap();
46 price_level.tail = Some(new_tail);
47 price_level.total_quantity += order_quantity;
48 price_level.order_count += 1;
49 if let Some(prev_order) = self.bid.order_pool.get_mut(pre_tail_idx).unwrap(){
50 prev_order.next = Some(new_tail);
51 };
52 return Ok(new_tail);
53 }
54 }
55 }
56 Entry::Vacant(_) => {
57 }
59 }
60
61 let mut new_price_level = PriceLevel{
62 head : None,
63 tail : None,
64 order_count : 0,
65 total_quantity : 0
66 };
67 if let Some(free_index) = self.bid.free_list.pop(){
68 self.bid.order_registry.insert(order_id, free_index);
69 self.bid.order_pool[free_index] = Some(order);
70 new_price_level.head = Some(free_index);
71 new_price_level.tail = Some(free_index);
72 new_price_level.order_count += 1;
73 new_price_level.total_quantity += order_quantity;
74 self.bid.price_map.entry(price).or_insert(new_price_level);
75 return Ok(free_index)
76 }
77 self.bid.order_pool.push(Some(order));
78 let new_index = self.bid.order_pool.len()-1;
79 self.bid.order_registry.insert(order_id, new_index);
80 new_price_level.head = Some(new_index);
81 new_price_level.tail = Some(new_index);
82 new_price_level.order_count += 1;
83 new_price_level.total_quantity += order_quantity;
84 self.bid.price_map.entry(price).or_insert(new_price_level);
85
86 Ok(new_index)
87 }
88
89 pub fn create_sell_order(&mut self, resting_order : OrderNode) -> Result<usize, anyhow::Error>{
90 let mut order = resting_order;
91 let order_quantity = order.current_quantity;
92 let price = order.market_limit;
93 let order_id = resting_order.order_id;
94
95 match self.ask.price_map.entry(price){
96 Entry::Occupied(mut entry) => {
97 let price_level = entry.get_mut();
98 if price_level.total_quantity == 0 || price_level.head == None || price_level.tail == None{
99 entry.remove();
100 }else {
101 order.prev = price_level.tail;
102 if let Some(free_index) = self.ask.free_list.pop(){
103 self.ask.order_registry.insert(order_id, free_index);
104 self.ask.order_pool[free_index] = Some(order);
105 let prev_tail_idx = price_level.tail.unwrap();
106 price_level.tail = Some(free_index);
107 price_level.total_quantity += order_quantity;
108 price_level.order_count += 1;
109 if let Some(prev_order) = self.ask.order_pool.get_mut(prev_tail_idx).unwrap(){
110 prev_order.next = Some(free_index);
111 };
112 return Ok(free_index);
113 }
114 else {
115 self.ask.order_pool.push(Some(order));
116 let new_tail = self.ask.order_pool.len() - 1;
117 self.ask.order_registry.insert(order_id, new_tail);
118 let prev_tail_idx = price_level.tail.unwrap();
119 price_level.tail = Some(new_tail);
120 price_level.total_quantity += order_quantity;
121 price_level.order_count += 1;
122 if let Some(prev_order) = self.ask.order_pool.get_mut(prev_tail_idx).unwrap(){
123 prev_order.next = Some(new_tail);
124 };
125 return Ok(new_tail);
126 }
127 }
128 }
129 Entry::Vacant(_) => {
130 }
132 }
133
134 let mut new_price_level = PriceLevel{
135 head : None,
136 tail : None,
137 order_count : 0,
138 total_quantity : 0
139 };
140 if let Some(free_index) = self.ask.free_list.pop(){
141 self.ask.order_registry.insert(order_id, free_index);
142 self.ask.order_pool[free_index] = Some(order);
143 new_price_level.head = Some(free_index);
144 new_price_level.tail = Some(free_index);
145 new_price_level.order_count += 1;
146 new_price_level.total_quantity += order_quantity;
147 self.ask.price_map.entry(price).or_insert(new_price_level);
148 return Ok(free_index)
149 }
150 self.ask.order_pool.push(Some(order));
151 let new_index = self.ask.order_pool.len()-1;
152 self.ask.order_registry.insert(order_id, new_index);
153 new_price_level.head = Some(new_index);
154 new_price_level.tail = Some(new_index);
155 new_price_level.order_count += 1;
156 new_price_level.total_quantity += order_quantity;
157 self.ask.price_map.entry(price).or_insert(new_price_level);
158
159 Ok(new_index)
160 }
161
162 pub fn cancel_order(&mut self, order_id : u64, order : EngineCancelOrder) -> Result<(), anyhow::Error>{
163 if order.is_buy_side {
164 let existing_index = self.bid.order_registry.get(&order_id);
165 if existing_index.is_none(){
166 return Err(anyhow!("index for the order doesn't exist in the local registry"));
167 }
168 let (prev, next, old_price, old_quantity) = {
169 match self.bid.order_pool[*existing_index.unwrap()].as_ref(){
170 Some(node) => {
171 (node.prev, node.next, node.market_limit, node.current_quantity)
172 }
173 None => {
174 return Err(anyhow!("order node doesn't exist at index for cancellation"));
175 }
176 }
177 };
178 if let Some(price_level) = self.bid.price_map.get_mut(&old_price){
179
180 if price_level.head.is_some() && price_level.tail.is_some(){
181 if *existing_index.unwrap() == price_level.head.unwrap() && *existing_index.unwrap() == price_level.tail.unwrap(){
182 self.bid.order_pool[*existing_index.unwrap()] = None;
183 price_level.head = None;
184 price_level.tail = None;
185 price_level.total_quantity = price_level.total_quantity.checked_sub(old_quantity).ok_or(anyhow!("error in subtracting total qty in order cancellation"))?;
186 price_level.order_count = price_level.order_count.checked_sub(1).ok_or(anyhow!("error is subtracting order qty in cancellation"))?;
187 self.bid.free_list.push(*existing_index.unwrap());
188 return Ok(());
189 }
190 else if *existing_index.unwrap() == price_level.tail.unwrap() {
191 if let Some(prev_index) = prev{
192 if let Some(possible_prev_node) = self.bid.order_pool.get_mut(prev_index){
193 if let Some(prev_node) = possible_prev_node{
194 prev_node.next = None;
195 price_level.tail = Some(prev_index);
196 }
197 }
198 self.bid.order_pool[*existing_index.unwrap()] = None;
199 price_level.total_quantity = price_level.total_quantity.checked_sub(old_quantity).ok_or(anyhow!("error in subtracting total qty in order cancellation"))?;
200 price_level.order_count = price_level.order_count.checked_sub(1).ok_or(anyhow!("error is subtracting order qty in cancellation"))?;
201 self.bid.free_list.push(*existing_index.unwrap());
202 return Ok(());
203 } else {
204 return Err(anyhow!("no prev node found for deletion of tail node"));
205 }
206 }
207 else if *existing_index.unwrap() == price_level.head.unwrap() {
208 if let Some(next_index) = next{
209 if let Some(possible_next_node) = self.bid.order_pool.get_mut(next_index){
210 if let Some(next_node) = possible_next_node{
211 next_node.prev = None;
212 price_level.head = Some(next_index);
213 }
214 }
215 self.bid.order_pool[*existing_index.unwrap()] = None;
216 price_level.total_quantity = price_level.total_quantity.checked_sub(old_quantity).ok_or(anyhow!("error in subtracting total qty in order cancellation"))?;
217 price_level.order_count = price_level.order_count.checked_sub(1).ok_or(anyhow!("error is subtracting order qty in cancellation"))?;
218 self.bid.free_list.push(*existing_index.unwrap());
219 return Ok(());
220 } else {
221 return Err(anyhow!("no next node found for deletion of head node"));
222 }
223 }
224 else {
225 if let Some(prev_index) = prev{
226 if let Some(possible_prev_node) = self.bid.order_pool.get_mut(prev_index){
227 if let Some(prev_node) = possible_prev_node{
228 prev_node.next = next
229 }
230 }
231 }
232 else {
233 return Err(anyhow!("no prev node found for deletion of middle node"));
234 }
235 if let Some(next_index) = next{
236 if let Some(possible_next_node) = self.bid.order_pool.get_mut(next_index){
237 if let Some(next_node) = possible_next_node{
238 next_node.prev = prev
239 }
240 }
241 }
242 else {
243 return Err(anyhow!("no next node found for deletion of middle node"));
244 }
245 self.bid.order_pool[*existing_index.unwrap()] = None;
246 price_level.total_quantity = price_level.total_quantity.checked_sub(old_quantity).ok_or(anyhow!("error in subtracting total qty in order cancellation"))?;
247 price_level.order_count = price_level.order_count.checked_sub(1).ok_or(anyhow!("error is subtracting order qty in cancellation"))?;
248 self.bid.free_list.push(*existing_index.unwrap());
249 return Ok(());
250 }
251 } else {
252 self.bid.price_map.remove(&old_price);
253 return Err(anyhow::anyhow!("head and tail corrupted so deleted"));
254 }
255 } else {
256 return Err(anyhow!("unable to get old price node to perform cancellation"));
257 }
258 } else {
259 let existing_index = self.ask.order_registry.get(&order_id);
260 if existing_index.is_none(){
261 return Err(anyhow!("index for the order doesn't exist in the local registry"));
262 }
263 let (prev, next, old_price, old_quantity) = {
264 match self.ask.order_pool[*existing_index.unwrap()].as_ref(){
265 Some(node) => {
266 (node.prev, node.next, node.market_limit, node.current_quantity)
267 }
268 None => {
269 return Err(anyhow!("order node doesn't exist at index for cancellation"));
270 }
271 }
272 };
273 if let Some(price_level) = self.ask.price_map.get_mut(&old_price){
274
275 if price_level.head.is_some() && price_level.tail.is_some(){
276 if *existing_index.unwrap() == price_level.head.unwrap() && *existing_index.unwrap() == price_level.tail.unwrap(){
277 self.ask.order_pool[*existing_index.unwrap()] = None;
278 price_level.head = None;
279 price_level.tail = None;
280 price_level.total_quantity = price_level.total_quantity.checked_sub(old_quantity).ok_or(anyhow!("error in subtracting total qty in order cancellation"))?;
281 price_level.order_count = price_level.order_count.checked_sub(1).ok_or(anyhow!("error is subtracting order qty in cancellation"))?;
282 self.ask.free_list.push(*existing_index.unwrap());
283 return Ok(());
284 }
285 else if *existing_index.unwrap() == price_level.tail.unwrap() {
286 if let Some(prev_index) = prev{
287 if let Some(possible_prev_node) = self.ask.order_pool.get_mut(prev_index){
288 if let Some(prev_node) = possible_prev_node{
289 prev_node.next = None;
290 price_level.tail = Some(prev_index);
291 }
292 }
293 self.ask.order_pool[*existing_index.unwrap()] = None;
294 price_level.total_quantity = price_level.total_quantity.checked_sub(old_quantity).ok_or(anyhow!("error in subtracting total qty in order cancellation"))?;
295 price_level.order_count = price_level.order_count.checked_sub(1).ok_or(anyhow!("error is subtracting order qty in cancellation"))?;
296 self.ask.free_list.push(*existing_index.unwrap());
297 return Ok(());
298 } else {
299 return Err(anyhow!("no prev node found for deletion of tail node"));
300 }
301 }
302 else if *existing_index.unwrap() == price_level.head.unwrap() {
303 if let Some(next_index) = next{
304 if let Some(possible_next_node) = self.ask.order_pool.get_mut(next_index){
305 if let Some(next_node) = possible_next_node{
306 next_node.prev = None;
307 price_level.head = Some(next_index);
308 }
309 }
310 self.ask.order_pool[*existing_index.unwrap()] = None;
311 price_level.total_quantity = price_level.total_quantity.checked_sub(old_quantity).ok_or(anyhow!("error in subtracting total qty in order cancellation"))?;
312 price_level.order_count = price_level.order_count.checked_sub(1).ok_or(anyhow!("error is subtracting order qty in cancellation"))?;
313 self.ask.free_list.push(*existing_index.unwrap());
314 return Ok(());
315 } else {
316 return Err(anyhow!("no next node found for deletion of head node"));
317 }
318 }
319 else {
320 if let Some(prev_index) = prev{
321 if let Some(possible_prev_node) = self.ask.order_pool.get_mut(prev_index){
322 if let Some(prev_node) = possible_prev_node{
323 prev_node.next = next
324 }
325 }
326 }
327 else {
328 return Err(anyhow!("no prev node found for deletion of middle node"));
329 }
330 if let Some(next_index) = next{
331 if let Some(possible_next_node) = self.ask.order_pool.get_mut(next_index){
332 if let Some(next_node) = possible_next_node{
333 next_node.prev = prev
334 }
335 }
336 }
337 else {
338 return Err(anyhow!("no next node found for deletion of middle node"));
339 }
340 self.ask.order_pool[*existing_index.unwrap()] = None;
341 price_level.total_quantity = price_level.total_quantity.checked_sub(old_quantity).ok_or(anyhow!("error in subtracting total qty in order cancellation"))?;
342 price_level.order_count = price_level.order_count.checked_sub(1).ok_or(anyhow!("error is subtracting order qty in cancellation"))?;
343 self.ask.free_list.push(*existing_index.unwrap());
344 return Ok(());
345 }
346 } else {
347 self.ask.price_map.remove(&old_price);
348 return Err(anyhow::anyhow!("head and tail corrupted so deleted"));
349 }
350 } else {
351 return Err(anyhow!("unable to get old price node to perform cancellation"));
352 }
353 }
354 }
355
356 pub fn modify_order(&mut self, order_id : u64, order : EngineModifyOrder) -> Result<Option<ModifyOutcome>, anyhow::Error>{
357 if order.is_buy_side{
358 let existing_index = self.bid.order_registry.get(&order_id);
359 if existing_index.is_none(){
360 return Err(anyhow!("index for the order doesn't exist in the local registry"));
361 }
362 let (old_initial_qty, old_current_qty, old_price) = {
363 match self.bid.order_pool[*existing_index.unwrap()].as_ref(){
364 Some(node) => {
365 (node.initial_quantity, node.current_quantity, node.market_limit)
366 }
367 None => {
368 return Err(anyhow!("order node not found at index for modification (buy)"));
369 }
370 }
371 };
372 if let Some(new_price) = order.new_price && let Some(new_qty) = order.new_quantity{
373 if new_price != old_price{
374 if let Ok(_) = self.cancel_order(order_id ,EngineCancelOrder { order_id : order.order_id, security_id : order.security_id, is_buy_side: order.is_buy_side,}){
375 return Ok(Some(ModifyOutcome::Both {new_price, new_initial_qty: new_qty, old_current_qty }));
376 }
377 }
378 return Ok(None);
379 } else if let Some(new_qty) = order.new_quantity {
380 if new_qty > old_initial_qty{
381 if let Ok(_) = self.cancel_order(order_id ,EngineCancelOrder { order_id : order.order_id,security_id : order.security_id, is_buy_side: order.is_buy_side,}){
382 return Ok(Some(ModifyOutcome::Requantized {old_price, new_initial_qty: new_qty, old_current_qty }))
383 }
384 return Ok(None);
385 }
386 else {
387 match self.bid.order_pool[*existing_index.unwrap()].as_mut(){
388 Some(order_node) => {
389 order_node.initial_quantity = new_qty;
390 return Ok(Some(ModifyOutcome::Inplace));
391 }
392 None => {
393 return Err(anyhow!("couldn't find order node to modify qty in-place (buy)"));
394 }
395 }
396 }
397 } else {
398 if let Ok(_) = self.cancel_order(order_id ,EngineCancelOrder { order_id : order.order_id,security_id : order.security_id, is_buy_side: order.is_buy_side,}){
399 return Ok(Some(ModifyOutcome::Repriced {new_price : order.new_price.unwrap(), old_initial_qty, old_current_qty }));
400 }
401 return Ok(None);
402 }
403 } else {
404 let existing_index = self.ask.order_registry.get(&order_id);
405 if existing_index.is_none(){
406 return Err(anyhow!("index for the order doesn't exist in the local registry"));
407 }
408 let (old_initial_qty, old_current_qty, old_price) = {
409 match self.ask.order_pool[*existing_index.unwrap()].as_ref(){
410 Some(node) => {
411 (node.initial_quantity, node.current_quantity, node.market_limit)
412 }
413 None => {
414 return Err(anyhow!("order node not found at index for modification (sell)"));
415 }
416 }
417 };
418
419 if let Some(new_price) = order.new_price && let Some(new_qty) = order.new_quantity{
420 if new_price != old_price{
421 if let Ok(_) = self.cancel_order(order_id ,EngineCancelOrder { order_id : order.order_id,security_id : order.security_id, is_buy_side: order.is_buy_side,}){
422 return Ok(Some(ModifyOutcome::Requantized {old_price, new_initial_qty: new_qty, old_current_qty }))
423 }
424 }
425 return Ok(None);
426 } else if let Some(new_qty) = order.new_quantity {
427 if new_qty > old_initial_qty{
428 if let Ok(_) = self.cancel_order(order_id ,EngineCancelOrder { order_id : order.order_id, security_id : order.security_id, is_buy_side: order.is_buy_side,}){
429 return Ok(Some(ModifyOutcome::Requantized { old_price, new_initial_qty: new_qty, old_current_qty }))
430 }
431 return Ok(None);
432 }
433 else {
434 match self.ask.order_pool[*existing_index.unwrap()].as_mut(){
435 Some(order_node) => {
436 order_node.initial_quantity = new_qty;
437 return Ok(Some(ModifyOutcome::Inplace));
438 }
439 None => {
440 return Err(anyhow!("couldn't find order node to modify qty in-place (sell)"));
441 }
442 }
443 }
444 }else {
445 if let Ok(_) = self.cancel_order(order_id ,EngineCancelOrder { order_id : order.order_id, security_id : order.security_id, is_buy_side: order.is_buy_side,}){
446 return Ok(Some(ModifyOutcome::Repriced { new_price : order.new_price.unwrap(), old_initial_qty, old_current_qty }));
447 }
448 return Ok(None);
449 }
450 }
451 }
452
453 pub fn depth(&self, levels_count : Option<u32>) -> Result<BookDepth, anyhow::Error>{
454 let timer = Instant::now();
455
456 let ask_iter = self.ask.price_map.iter().rev();
457 let bid_iter = self.bid.price_map.iter();
458
459 let ask_depth : Vec<_> = match levels_count {
460 Some(n) => ask_iter.take(n as usize)
461 .map(|(price, price_level)| PriceLevelDepth {
462 price_level : *price,
463 quantity : price_level.total_quantity
464 })
465 .collect(),
466 None => ask_iter.map(|(price, price_level)| PriceLevelDepth {
467 price_level : *price,
468 quantity : price_level.total_quantity
469 }).collect()
470 };
471 let bid_depth = match levels_count {
472 Some(n) => bid_iter.take(n as usize)
473 .map(|(price, price_level)| PriceLevelDepth {
474 price_level : *price,
475 quantity : price_level.total_quantity
476 })
477 .collect(),
478 None => bid_iter.map(|(price, price_level)| PriceLevelDepth {
479 price_level : *price,
480 quantity : price_level.total_quantity
481 }).collect()
482 };
483 let elapsed_time = timer.elapsed().as_micros() as f64;
484 Ok(BookDepth { bid_depth, ask_depth, timer : elapsed_time })
485 }
486}
487
488#[derive(Debug)]
489pub struct HalfBook{
490 pub price_map : BTreeMap<u32, PriceLevel>,
491 pub order_registry : HashMap<u64, usize>,
492 pub order_pool : Vec<Option<OrderNode>>,
493 pub free_list : Vec<usize>, }
495
496impl HalfBook {
497 pub fn new() -> Self{
498 Self { price_map: BTreeMap::new(), order_registry : HashMap::new(), order_pool: Vec::new(), free_list: Vec::new()}
499 }
500}