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