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