Skip to main content

matchcore/orderbook/book/
price_level.rs

1use super::QueueEntry;
2use crate::{OrderId, Quantity, RestingLimitOrder, SequenceNumber};
3
4use std::collections::{HashMap, VecDeque};
5
6/// Price level that manages the status of the orders with the same price.
7/// It does not store the orders themselves, but only the time priority information of the orders.
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[derive(Debug, Clone)]
10pub struct PriceLevel {
11    /// Total visible quantity at this price level
12    pub(crate) visible_quantity: Quantity,
13    /// Total hidden quantity at this price level
14    pub(crate) hidden_quantity: Quantity,
15    /// Number of orders at this price level
16    order_count: u64,
17    /// The time priority queue of this price level
18    queue: VecDeque<QueueEntry>,
19}
20
21impl Default for PriceLevel {
22    fn default() -> Self {
23        Self::new()
24    }
25}
26
27impl PriceLevel {
28    /// Create a new price level
29    pub fn new() -> Self {
30        Self {
31            visible_quantity: Quantity(0),
32            hidden_quantity: Quantity(0),
33            order_count: 0,
34            queue: VecDeque::new(),
35        }
36    }
37
38    /// Get the visible quantity at this price level
39    pub fn visible_quantity(&self) -> Quantity {
40        self.visible_quantity
41    }
42
43    /// Get the hidden quantity at this price level
44    pub fn hidden_quantity(&self) -> Quantity {
45        self.hidden_quantity
46    }
47
48    /// Get the total quantity at this price level (visible + hidden)
49    pub fn total_quantity(&self) -> Quantity {
50        self.visible_quantity + self.hidden_quantity
51    }
52
53    /// Get the number of orders at this price level
54    pub fn order_count(&self) -> u64 {
55        self.order_count
56    }
57
58    /// Get the time priority queue of this price level
59    pub fn queue(&self) -> &VecDeque<QueueEntry> {
60        &self.queue
61    }
62
63    /// Increment the number of orders at this price level
64    pub(crate) fn increment_order_count(&mut self) {
65        self.order_count += 1;
66    }
67
68    /// Decrement the number of orders at this price level
69    pub(crate) fn decrement_order_count(&mut self) {
70        self.order_count -= 1;
71    }
72
73    /// Check if the price level is empty
74    pub(crate) fn is_empty(&self) -> bool {
75        self.order_count == 0
76    }
77}
78
79impl PriceLevel {
80    /// Push a queue entry to the queue
81    pub(crate) fn push(&mut self, queue_entry: QueueEntry) {
82        self.queue.push_back(queue_entry);
83    }
84
85    /// Attempt to peek the first queue entry in the queue without removing it
86    pub(crate) fn peek(&self) -> Option<QueueEntry> {
87        self.queue.front().copied()
88    }
89
90    /// Attempt to pop the first queue entry in the queue
91    pub(crate) fn pop(&mut self) -> Option<QueueEntry> {
92        self.queue.pop_front()
93    }
94
95    /// Add an order entry to the price level
96    pub(crate) fn add_order_entry(
97        &mut self,
98        queue_entry: QueueEntry,
99        visible: Quantity,
100        hidden: Quantity,
101    ) {
102        self.visible_quantity += visible;
103        self.hidden_quantity += hidden;
104
105        self.push(queue_entry);
106        self.increment_order_count();
107    }
108
109    /// Mark an order as removed from the price level
110    /// Note that it does not remove the queue entry from the queue.
111    /// The stale queue entry will be cleaned up when the order is peeked from the queue.
112    pub(crate) fn mark_order_removed(&mut self, visible: Quantity, hidden: Quantity) {
113        self.visible_quantity -= visible;
114        self.hidden_quantity -= hidden;
115        self.decrement_order_count();
116    }
117
118    /// Pop the first queue entry from the price level and remove the order from the order book
119    /// If the price level is empty, do nothing
120    /// Note that it does not update the quantity of the price level
121    pub(crate) fn remove_head_order(
122        &mut self,
123        limit_orders: &mut HashMap<OrderId, RestingLimitOrder>,
124    ) {
125        let Some(queue_entry) = self.pop() else {
126            return;
127        };
128        limit_orders.remove(&queue_entry.order_id());
129        self.decrement_order_count();
130    }
131
132    /// Apply the replenished quantity to the price level
133    pub(crate) fn apply_replenishment(&mut self, replenished: Quantity) {
134        self.visible_quantity += replenished;
135        self.hidden_quantity -= replenished;
136    }
137
138    /// Reprioritize the front order and move it to the back of the queue
139    ///
140    /// # Panics
141    /// Panics if the queue is empty.
142    pub(crate) fn reprioritize_front(&mut self, time_priority: SequenceNumber) {
143        let queue_entry = self.pop().unwrap();
144        self.push(queue_entry.reprioritize(time_priority));
145    }
146}
147
148#[cfg(test)]
149mod tests {
150    use crate::*;
151    use crate::{LimitOrder, OrderFlags, Price, Quantity, QuantityPolicy, Side, TimeInForce};
152
153    use std::collections::HashMap;
154
155    #[test]
156    fn test_total_quantity() {
157        let mut price_level = PriceLevel::new();
158        assert_eq!(price_level.total_quantity(), Quantity(0));
159
160        price_level.visible_quantity = Quantity(10);
161        price_level.hidden_quantity = Quantity(20);
162        assert_eq!(price_level.total_quantity(), Quantity(30));
163    }
164
165    #[test]
166    fn test_order_count() {
167        let mut price_level = PriceLevel::new();
168        assert_eq!(price_level.order_count(), 0);
169        assert!(price_level.is_empty());
170
171        price_level.increment_order_count();
172        assert_eq!(price_level.order_count(), 1);
173        assert!(!price_level.is_empty());
174
175        price_level.decrement_order_count();
176        assert_eq!(price_level.order_count(), 0);
177        assert!(price_level.is_empty());
178    }
179
180    #[test]
181    fn test_add_order_entry_and_mark_order_removed() {
182        let mut price_level = PriceLevel::new();
183        assert_eq!(price_level.visible_quantity, Quantity(0));
184        assert_eq!(price_level.hidden_quantity, Quantity(0));
185        assert_eq!(price_level.order_count(), 0);
186
187        price_level.add_order_entry(
188            QueueEntry::new(SequenceNumber(0), OrderId(0)),
189            Quantity(10),
190            Quantity(0),
191        );
192        assert_eq!(price_level.visible_quantity, Quantity(10));
193        assert_eq!(price_level.hidden_quantity, Quantity(0));
194        assert_eq!(price_level.order_count(), 1);
195
196        price_level.add_order_entry(
197            QueueEntry::new(SequenceNumber(1), OrderId(1)),
198            Quantity(20),
199            Quantity(0),
200        );
201        assert_eq!(price_level.visible_quantity, Quantity(30));
202        assert_eq!(price_level.hidden_quantity, Quantity(0));
203        assert_eq!(price_level.order_count(), 2);
204
205        price_level.add_order_entry(
206            QueueEntry::new(SequenceNumber(2), OrderId(2)),
207            Quantity(30),
208            Quantity(0),
209        );
210        assert_eq!(price_level.visible_quantity, Quantity(60));
211        assert_eq!(price_level.hidden_quantity, Quantity(0));
212        assert_eq!(price_level.order_count(), 3);
213
214        price_level.add_order_entry(
215            QueueEntry::new(SequenceNumber(3), OrderId(3)),
216            Quantity(40),
217            Quantity(0),
218        );
219        assert_eq!(price_level.visible_quantity, Quantity(100));
220        assert_eq!(price_level.hidden_quantity, Quantity(0));
221        assert_eq!(price_level.order_count(), 4);
222
223        price_level.add_order_entry(
224            QueueEntry::new(SequenceNumber(4), OrderId(4)),
225            Quantity(50),
226            Quantity(50),
227        );
228        assert_eq!(price_level.visible_quantity, Quantity(150));
229        assert_eq!(price_level.hidden_quantity, Quantity(50));
230        assert_eq!(price_level.order_count(), 5);
231
232        price_level.mark_order_removed(Quantity(10), Quantity(0));
233        assert_eq!(price_level.visible_quantity, Quantity(140));
234        assert_eq!(price_level.hidden_quantity, Quantity(50));
235        assert_eq!(price_level.order_count(), 4);
236
237        price_level.mark_order_removed(Quantity(20), Quantity(0));
238        assert_eq!(price_level.visible_quantity, Quantity(120));
239        assert_eq!(price_level.hidden_quantity, Quantity(50));
240        assert_eq!(price_level.order_count(), 3);
241
242        price_level.mark_order_removed(Quantity(30), Quantity(0));
243        assert_eq!(price_level.visible_quantity, Quantity(90));
244        assert_eq!(price_level.hidden_quantity, Quantity(50));
245        assert_eq!(price_level.order_count(), 2);
246
247        price_level.mark_order_removed(Quantity(40), Quantity(0));
248        assert_eq!(price_level.visible_quantity, Quantity(50));
249        assert_eq!(price_level.hidden_quantity, Quantity(50));
250        assert_eq!(price_level.order_count(), 1);
251
252        price_level.mark_order_removed(Quantity(50), Quantity(50));
253        assert_eq!(price_level.visible_quantity, Quantity(0));
254        assert_eq!(price_level.hidden_quantity, Quantity(0));
255        assert_eq!(price_level.order_count(), 0);
256    }
257
258    #[test]
259    fn test_remove_head_order() {
260        let mut limit_orders = HashMap::new();
261
262        let mut price_level = PriceLevel::new();
263        assert!(price_level.peek().is_none());
264
265        limit_orders.insert(
266            OrderId(0),
267            RestingLimitOrder::new(
268                SequenceNumber(0),
269                0,
270                LimitOrder::new(
271                    Price(100),
272                    QuantityPolicy::Standard {
273                        quantity: Quantity(10),
274                    },
275                    OrderFlags::new(Side::Buy, true, TimeInForce::Gtc),
276                ),
277            ),
278        );
279        price_level.add_order_entry(
280            QueueEntry::new(SequenceNumber(0), OrderId(0)),
281            Quantity(10),
282            Quantity(0),
283        );
284        assert_eq!(
285            price_level.peek(),
286            Some(QueueEntry::new(SequenceNumber(0), OrderId(0)))
287        );
288
289        price_level.remove_head_order(&mut limit_orders);
290        assert!(price_level.peek().is_none());
291
292        limit_orders.insert(
293            OrderId(1),
294            RestingLimitOrder::new(
295                SequenceNumber(1),
296                0,
297                LimitOrder::new(
298                    Price(100),
299                    QuantityPolicy::Standard {
300                        quantity: Quantity(20),
301                    },
302                    OrderFlags::new(Side::Buy, true, TimeInForce::Gtc),
303                ),
304            ),
305        );
306        price_level.add_order_entry(
307            QueueEntry::new(SequenceNumber(1), OrderId(1)),
308            Quantity(20),
309            Quantity(0),
310        );
311        assert_eq!(
312            price_level.peek(),
313            Some(QueueEntry::new(SequenceNumber(1), OrderId(1)))
314        );
315
316        limit_orders.insert(
317            OrderId(2),
318            RestingLimitOrder::new(
319                SequenceNumber(2),
320                0,
321                LimitOrder::new(
322                    Price(100),
323                    QuantityPolicy::Standard {
324                        quantity: Quantity(30),
325                    },
326                    OrderFlags::new(Side::Buy, true, TimeInForce::Gtc),
327                ),
328            ),
329        );
330        price_level.add_order_entry(
331            QueueEntry::new(SequenceNumber(2), OrderId(2)),
332            Quantity(30),
333            Quantity(0),
334        );
335        assert_eq!(
336            price_level.peek(),
337            Some(QueueEntry::new(SequenceNumber(1), OrderId(1)))
338        );
339
340        price_level.remove_head_order(&mut limit_orders);
341        assert_eq!(
342            price_level.peek(),
343            Some(QueueEntry::new(SequenceNumber(2), OrderId(2)))
344        );
345
346        price_level.remove_head_order(&mut limit_orders);
347        assert!(price_level.peek().is_none());
348    }
349
350    #[test]
351    fn test_reprioritize_front() {
352        let mut price_level = PriceLevel::new();
353        assert_eq!(price_level.peek(), None);
354
355        price_level.push(QueueEntry::new(SequenceNumber(0), OrderId(0)));
356        assert_eq!(
357            price_level.peek(),
358            Some(QueueEntry::new(SequenceNumber(0), OrderId(0)))
359        );
360
361        price_level.reprioritize_front(SequenceNumber(1));
362        assert_eq!(
363            price_level.peek(),
364            Some(QueueEntry::new(SequenceNumber(1), OrderId(0)))
365        );
366
367        price_level.push(QueueEntry::new(SequenceNumber(2), OrderId(2)));
368        assert_eq!(
369            price_level.peek(),
370            Some(QueueEntry::new(SequenceNumber(1), OrderId(0)))
371        );
372
373        price_level.reprioritize_front(SequenceNumber(3));
374        assert_eq!(
375            price_level.peek(),
376            Some(QueueEntry::new(SequenceNumber(2), OrderId(2)))
377        );
378
379        price_level.reprioritize_front(SequenceNumber(4));
380        assert_eq!(
381            price_level.peek(),
382            Some(QueueEntry::new(SequenceNumber(3), OrderId(0)))
383        );
384    }
385
386    #[test]
387    fn test_apply_replenishment() {
388        let mut price_level = PriceLevel::new();
389        assert_eq!(price_level.visible_quantity, Quantity(0));
390        assert_eq!(price_level.hidden_quantity, Quantity(0));
391
392        price_level.visible_quantity = Quantity(10);
393        price_level.hidden_quantity = Quantity(100);
394
395        price_level.apply_replenishment(Quantity(10));
396        assert_eq!(price_level.visible_quantity, Quantity(20));
397        assert_eq!(price_level.hidden_quantity, Quantity(90));
398
399        price_level.apply_replenishment(Quantity(10));
400        assert_eq!(price_level.visible_quantity, Quantity(30));
401        assert_eq!(price_level.hidden_quantity, Quantity(80));
402
403        price_level.apply_replenishment(Quantity(10));
404        assert_eq!(price_level.visible_quantity, Quantity(40));
405        assert_eq!(price_level.hidden_quantity, Quantity(70));
406
407        price_level.apply_replenishment(Quantity(10));
408        assert_eq!(price_level.visible_quantity, Quantity(50));
409        assert_eq!(price_level.hidden_quantity, Quantity(60));
410
411        price_level.apply_replenishment(Quantity(10));
412        assert_eq!(price_level.visible_quantity, Quantity(60));
413        assert_eq!(price_level.hidden_quantity, Quantity(50));
414
415        price_level.apply_replenishment(Quantity(10));
416        assert_eq!(price_level.visible_quantity, Quantity(70));
417        assert_eq!(price_level.hidden_quantity, Quantity(40));
418
419        price_level.apply_replenishment(Quantity(10));
420        assert_eq!(price_level.visible_quantity, Quantity(80));
421        assert_eq!(price_level.hidden_quantity, Quantity(30));
422
423        price_level.apply_replenishment(Quantity(10));
424        assert_eq!(price_level.visible_quantity, Quantity(90));
425        assert_eq!(price_level.hidden_quantity, Quantity(20));
426
427        price_level.apply_replenishment(Quantity(10));
428        assert_eq!(price_level.visible_quantity, Quantity(100));
429        assert_eq!(price_level.hidden_quantity, Quantity(10));
430
431        price_level.apply_replenishment(Quantity(10));
432        assert_eq!(price_level.visible_quantity, Quantity(110));
433        assert_eq!(price_level.hidden_quantity, Quantity(0));
434    }
435}