nautilus_model/orderbook/
ladder.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16// Under development
17#![allow(dead_code)]
18
19//! Represents a ladder of price levels for one side of an order book.
20
21use std::{
22    cmp::Ordering,
23    collections::{BTreeMap, HashMap},
24    fmt::{Display, Formatter},
25};
26
27use nautilus_core::UnixNanos;
28
29use crate::{
30    data::order::{BookOrder, OrderId},
31    enums::{OrderSide, OrderSideSpecified},
32    orderbook::BookLevel,
33    types::{Price, Quantity},
34};
35
36/// Represents a price level with a specified side in an order books ladder.
37#[derive(Clone, Copy, Debug, Eq)]
38#[cfg_attr(
39    feature = "python",
40    pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.model")
41)]
42pub struct BookPrice {
43    pub value: Price,
44    pub side: OrderSide,
45}
46
47impl BookPrice {
48    /// Creates a new [`BookPrice`] instance.
49    #[must_use]
50    pub fn new(value: Price, side: OrderSide) -> Self {
51        Self { value, side }
52    }
53}
54
55impl PartialOrd for BookPrice {
56    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
57        Some(self.cmp(other))
58    }
59}
60
61impl PartialEq for BookPrice {
62    fn eq(&self, other: &Self) -> bool {
63        self.value == other.value
64    }
65}
66
67impl Ord for BookPrice {
68    fn cmp(&self, other: &Self) -> Ordering {
69        match self.side.as_specified() {
70            OrderSideSpecified::Buy => other.value.cmp(&self.value),
71            OrderSideSpecified::Sell => self.value.cmp(&other.value),
72        }
73    }
74}
75
76impl Display for BookPrice {
77    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
78        write!(f, "{}", self.value)
79    }
80}
81
82/// Represents a ladder of price levels for one side of an order book.
83#[derive(Clone, Debug)]
84pub(crate) struct BookLadder {
85    pub side: OrderSide,
86    pub levels: BTreeMap<BookPrice, BookLevel>,
87    pub cache: HashMap<u64, BookPrice>,
88}
89
90impl BookLadder {
91    /// Creates a new [`Ladder`] instance.
92    #[must_use]
93    pub fn new(side: OrderSide) -> Self {
94        Self {
95            side,
96            levels: BTreeMap::new(),
97            cache: HashMap::new(),
98        }
99    }
100
101    /// Returns the number of price levels in the ladder.
102    #[must_use]
103    pub fn len(&self) -> usize {
104        self.levels.len()
105    }
106
107    /// Returns true if the ladder has no price levels.
108    #[must_use]
109    pub fn is_empty(&self) -> bool {
110        self.levels.is_empty()
111    }
112
113    /// Adds multiple orders to the ladder.
114    pub fn add_bulk(&mut self, orders: Vec<BookOrder>) {
115        for order in orders {
116            self.add(order);
117        }
118    }
119
120    /// Removes all orders and price levels from the ladder.
121    pub fn clear(&mut self) {
122        self.levels.clear();
123        self.cache.clear();
124    }
125
126    /// Adds an order to the ladder at its price level.
127    pub fn add(&mut self, order: BookOrder) {
128        let book_price = order.to_book_price();
129        self.cache.insert(order.order_id, book_price);
130
131        match self.levels.get_mut(&book_price) {
132            Some(level) => {
133                level.add(order);
134            }
135            None => {
136                let level = BookLevel::from_order(order);
137                self.levels.insert(book_price, level);
138            }
139        }
140    }
141
142    /// Updates an existing order in the ladder, moving it to a new price level if needed.
143    pub fn update(&mut self, order: BookOrder) {
144        let price = self.cache.get(&order.order_id).copied();
145        if let Some(price) = price {
146            if let Some(level) = self.levels.get_mut(&price) {
147                if order.price == level.price.value {
148                    // Update at current price level
149                    level.update(order);
150                    return;
151                }
152
153                // Price update: delete and insert at new level
154                self.cache.remove(&order.order_id);
155                level.delete(&order);
156                if level.is_empty() {
157                    self.levels.remove(&price);
158                }
159            }
160        }
161
162        self.add(order);
163    }
164
165    /// Deletes an order from the ladder.
166    pub fn delete(&mut self, order: BookOrder, sequence: u64, ts_event: UnixNanos) {
167        self.remove(order.order_id, sequence, ts_event);
168    }
169
170    /// Removes an order by its ID from the ladder.
171    pub fn remove(&mut self, order_id: OrderId, sequence: u64, ts_event: UnixNanos) {
172        if let Some(price) = self.cache.remove(&order_id) {
173            if let Some(level) = self.levels.get_mut(&price) {
174                level.remove_by_id(order_id, sequence, ts_event);
175                if level.is_empty() {
176                    self.levels.remove(&price);
177                }
178            }
179        }
180    }
181
182    /// Returns the total size of all orders in the ladder.
183    #[must_use]
184    pub fn sizes(&self) -> f64 {
185        self.levels
186            .values()
187            .map(super::level::BookLevel::size)
188            .sum()
189    }
190
191    /// Returns the total value exposure (price * size) of all orders in the ladder.
192    #[must_use]
193    pub fn exposures(&self) -> f64 {
194        self.levels
195            .values()
196            .map(super::level::BookLevel::exposure)
197            .sum()
198    }
199
200    /// Returns the best price level in the ladder.
201    #[must_use]
202    pub fn top(&self) -> Option<&BookLevel> {
203        match self.levels.iter().next() {
204            Some((_, l)) => Option::Some(l),
205            None => Option::None,
206        }
207    }
208
209    /// Simulates fills for an order against this ladder's liquidity.
210    /// Returns a list of (price, size) tuples representing the simulated fills.
211    #[must_use]
212    pub fn simulate_fills(&self, order: &BookOrder) -> Vec<(Price, Quantity)> {
213        let is_reversed = self.side == OrderSide::Buy;
214        let mut fills = Vec::new();
215        let mut cumulative_denominator = Quantity::zero(order.size.precision);
216        let target = order.size;
217
218        for level in self.levels.values() {
219            if (is_reversed && level.price.value < order.price)
220                || (!is_reversed && level.price.value > order.price)
221            {
222                break;
223            }
224
225            for book_order in level.orders.values() {
226                let current = book_order.size;
227                if cumulative_denominator + current >= target {
228                    // This order has filled us, add fill and return
229                    let remainder = target - cumulative_denominator;
230                    if remainder.is_positive() {
231                        fills.push((book_order.price, remainder));
232                    }
233                    return fills;
234                }
235
236                // Add this fill and continue
237                fills.push((book_order.price, current));
238                cumulative_denominator += current;
239            }
240        }
241
242        fills
243    }
244}
245
246////////////////////////////////////////////////////////////////////////////////
247// Tests
248////////////////////////////////////////////////////////////////////////////////
249#[cfg(test)]
250mod tests {
251    use rstest::rstest;
252
253    use crate::{
254        data::order::BookOrder,
255        enums::OrderSide,
256        orderbook::ladder::{BookLadder, BookPrice},
257        types::{Price, Quantity},
258    };
259
260    #[rstest]
261    fn test_book_price_bid_sorting() {
262        let mut bid_prices = [
263            BookPrice::new(Price::from("2.0"), OrderSide::Buy),
264            BookPrice::new(Price::from("4.0"), OrderSide::Buy),
265            BookPrice::new(Price::from("1.0"), OrderSide::Buy),
266            BookPrice::new(Price::from("3.0"), OrderSide::Buy),
267        ];
268        bid_prices.sort();
269        assert_eq!(bid_prices[0].value.as_f64(), 4.0);
270    }
271
272    #[rstest]
273    fn test_book_price_ask_sorting() {
274        let mut ask_prices = [
275            BookPrice::new(Price::from("2.0"), OrderSide::Sell),
276            BookPrice::new(Price::from("4.0"), OrderSide::Sell),
277            BookPrice::new(Price::from("1.0"), OrderSide::Sell),
278            BookPrice::new(Price::from("3.0"), OrderSide::Sell),
279        ];
280
281        ask_prices.sort();
282        assert_eq!(ask_prices[0].value.as_f64(), 1.0);
283    }
284
285    #[rstest]
286    fn test_add_single_order() {
287        let mut ladder = BookLadder::new(OrderSide::Buy);
288        let order = BookOrder::new(OrderSide::Buy, Price::from("10.00"), Quantity::from(20), 0);
289
290        ladder.add(order);
291        assert_eq!(ladder.len(), 1);
292        assert_eq!(ladder.sizes(), 20.0);
293        assert_eq!(ladder.exposures(), 200.0);
294        assert_eq!(ladder.top().unwrap().price.value.as_f64(), 10.0);
295    }
296
297    #[rstest]
298    fn test_add_multiple_buy_orders() {
299        let mut ladder = BookLadder::new(OrderSide::Buy);
300        let order1 = BookOrder::new(OrderSide::Buy, Price::from("10.00"), Quantity::from(20), 0);
301        let order2 = BookOrder::new(OrderSide::Buy, Price::from("9.00"), Quantity::from(30), 1);
302        let order3 = BookOrder::new(OrderSide::Buy, Price::from("9.00"), Quantity::from(50), 2);
303        let order4 = BookOrder::new(OrderSide::Buy, Price::from("8.00"), Quantity::from(200), 3);
304
305        ladder.add_bulk(vec![order1, order2, order3, order4]);
306        assert_eq!(ladder.len(), 3);
307        assert_eq!(ladder.sizes(), 300.0);
308        assert_eq!(ladder.exposures(), 2520.0);
309        assert_eq!(ladder.top().unwrap().price.value.as_f64(), 10.0);
310    }
311
312    #[rstest]
313    fn test_add_multiple_sell_orders() {
314        let mut ladder = BookLadder::new(OrderSide::Sell);
315        let order1 = BookOrder::new(OrderSide::Sell, Price::from("11.00"), Quantity::from(20), 0);
316        let order2 = BookOrder::new(OrderSide::Sell, Price::from("12.00"), Quantity::from(30), 1);
317        let order3 = BookOrder::new(OrderSide::Sell, Price::from("12.00"), Quantity::from(50), 2);
318        let order4 = BookOrder::new(
319            OrderSide::Sell,
320            Price::from("13.00"),
321            Quantity::from(200),
322            0,
323        );
324
325        ladder.add_bulk(vec![order1, order2, order3, order4]);
326        assert_eq!(ladder.len(), 3);
327        assert_eq!(ladder.sizes(), 300.0);
328        assert_eq!(ladder.exposures(), 3780.0);
329        assert_eq!(ladder.top().unwrap().price.value.as_f64(), 11.0);
330    }
331
332    #[rstest]
333    fn test_add_to_same_price_level() {
334        let mut ladder = BookLadder::new(OrderSide::Buy);
335        let order1 = BookOrder::new(OrderSide::Buy, Price::from("10.00"), Quantity::from(20), 1);
336        let order2 = BookOrder::new(OrderSide::Buy, Price::from("10.00"), Quantity::from(30), 2);
337
338        ladder.add(order1);
339        ladder.add(order2);
340
341        assert_eq!(ladder.len(), 1);
342        assert_eq!(ladder.sizes(), 50.0);
343        assert_eq!(ladder.exposures(), 500.0);
344    }
345
346    #[rstest]
347    fn test_add_descending_buy_orders() {
348        let mut ladder = BookLadder::new(OrderSide::Buy);
349        let order1 = BookOrder::new(OrderSide::Buy, Price::from("9.00"), Quantity::from(20), 1);
350        let order2 = BookOrder::new(OrderSide::Buy, Price::from("8.00"), Quantity::from(30), 2);
351
352        ladder.add(order1);
353        ladder.add(order2);
354
355        assert_eq!(ladder.top().unwrap().price.value, Price::from("9.00"));
356    }
357
358    #[rstest]
359    fn test_add_ascending_sell_orders() {
360        let mut ladder = BookLadder::new(OrderSide::Sell);
361        let order1 = BookOrder::new(OrderSide::Sell, Price::from("8.00"), Quantity::from(20), 1);
362        let order2 = BookOrder::new(OrderSide::Sell, Price::from("9.00"), Quantity::from(30), 2);
363
364        ladder.add(order1);
365        ladder.add(order2);
366
367        assert_eq!(ladder.top().unwrap().price.value, Price::from("8.00"));
368    }
369
370    #[rstest]
371    fn test_update_buy_order_price() {
372        let mut ladder = BookLadder::new(OrderSide::Buy);
373        let order = BookOrder::new(OrderSide::Buy, Price::from("11.00"), Quantity::from(20), 1);
374
375        ladder.add(order);
376        let order = BookOrder::new(OrderSide::Buy, Price::from("11.10"), Quantity::from(20), 1);
377
378        ladder.update(order);
379        assert_eq!(ladder.len(), 1);
380        assert_eq!(ladder.sizes(), 20.0);
381        assert_eq!(ladder.exposures(), 222.0);
382        assert_eq!(ladder.top().unwrap().price.value.as_f64(), 11.1);
383    }
384
385    #[rstest]
386    fn test_update_sell_order_price() {
387        let mut ladder = BookLadder::new(OrderSide::Sell);
388        let order = BookOrder::new(OrderSide::Sell, Price::from("11.00"), Quantity::from(20), 1);
389
390        ladder.add(order);
391
392        let order = BookOrder::new(OrderSide::Sell, Price::from("11.10"), Quantity::from(20), 1);
393
394        ladder.update(order);
395        assert_eq!(ladder.len(), 1);
396        assert_eq!(ladder.sizes(), 20.0);
397        assert_eq!(ladder.exposures(), 222.0);
398        assert_eq!(ladder.top().unwrap().price.value.as_f64(), 11.1);
399    }
400
401    #[rstest]
402    fn test_update_buy_order_size() {
403        let mut ladder = BookLadder::new(OrderSide::Buy);
404        let order = BookOrder::new(OrderSide::Buy, Price::from("11.00"), Quantity::from(20), 1);
405
406        ladder.add(order);
407
408        let order = BookOrder::new(OrderSide::Buy, Price::from("11.00"), Quantity::from(10), 1);
409
410        ladder.update(order);
411        assert_eq!(ladder.len(), 1);
412        assert_eq!(ladder.sizes(), 10.0);
413        assert_eq!(ladder.exposures(), 110.0);
414        assert_eq!(ladder.top().unwrap().price.value.as_f64(), 11.0);
415    }
416
417    #[rstest]
418    fn test_update_sell_order_size() {
419        let mut ladder = BookLadder::new(OrderSide::Sell);
420        let order = BookOrder::new(OrderSide::Sell, Price::from("11.00"), Quantity::from(20), 1);
421
422        ladder.add(order);
423
424        let order = BookOrder::new(OrderSide::Sell, Price::from("11.00"), Quantity::from(10), 1);
425
426        ladder.update(order);
427        assert_eq!(ladder.len(), 1);
428        assert_eq!(ladder.sizes(), 10.0);
429        assert_eq!(ladder.exposures(), 110.0);
430        assert_eq!(ladder.top().unwrap().price.value.as_f64(), 11.0);
431    }
432
433    #[rstest]
434    fn test_delete_non_existing_order() {
435        let mut ladder = BookLadder::new(OrderSide::Buy);
436        let order = BookOrder::new(OrderSide::Buy, Price::from("10.00"), Quantity::from(20), 1);
437
438        ladder.delete(order, 0, 0.into());
439
440        assert_eq!(ladder.len(), 0);
441    }
442
443    #[rstest]
444    fn test_delete_buy_order() {
445        let mut ladder = BookLadder::new(OrderSide::Buy);
446        let order = BookOrder::new(OrderSide::Buy, Price::from("11.00"), Quantity::from(20), 1);
447
448        ladder.add(order);
449
450        let order = BookOrder::new(OrderSide::Buy, Price::from("11.00"), Quantity::from(10), 1);
451
452        ladder.delete(order, 0, 0.into());
453        assert_eq!(ladder.len(), 0);
454        assert_eq!(ladder.sizes(), 0.0);
455        assert_eq!(ladder.exposures(), 0.0);
456        assert_eq!(ladder.top(), None);
457    }
458
459    #[rstest]
460    fn test_delete_sell_order() {
461        let mut ladder = BookLadder::new(OrderSide::Sell);
462        let order = BookOrder::new(OrderSide::Sell, Price::from("10.00"), Quantity::from(10), 1);
463
464        ladder.add(order);
465
466        let order = BookOrder::new(OrderSide::Sell, Price::from("10.00"), Quantity::from(10), 1);
467
468        ladder.delete(order, 0, 0.into());
469        assert_eq!(ladder.len(), 0);
470        assert_eq!(ladder.sizes(), 0.0);
471        assert_eq!(ladder.exposures(), 0.0);
472        assert_eq!(ladder.top(), None);
473    }
474
475    #[rstest]
476    fn test_simulate_fills_with_empty_book() {
477        let ladder = BookLadder::new(OrderSide::Buy);
478        let order = BookOrder::new(OrderSide::Buy, Price::max(2), Quantity::from(500), 1);
479
480        let fills = ladder.simulate_fills(&order);
481
482        assert!(fills.is_empty());
483    }
484
485    #[rstest]
486    #[case(OrderSide::Buy, Price::max(2), OrderSide::Sell)]
487    #[case(OrderSide::Sell, Price::min(2), OrderSide::Buy)]
488    fn test_simulate_order_fills_with_no_size(
489        #[case] side: OrderSide,
490        #[case] price: Price,
491        #[case] ladder_side: OrderSide,
492    ) {
493        let ladder = BookLadder::new(ladder_side);
494        let order = BookOrder {
495            price, // <-- Simulate a MARKET order
496            size: Quantity::from(500),
497            side,
498            order_id: 2,
499        };
500
501        let fills = ladder.simulate_fills(&order);
502
503        assert!(fills.is_empty());
504    }
505
506    #[rstest]
507    #[case(OrderSide::Buy, OrderSide::Sell, Price::from("60.0"))]
508    #[case(OrderSide::Sell, OrderSide::Buy, Price::from("40.0"))]
509    fn test_simulate_order_fills_buy_when_far_from_market(
510        #[case] order_side: OrderSide,
511        #[case] ladder_side: OrderSide,
512        #[case] ladder_price: Price,
513    ) {
514        let mut ladder = BookLadder::new(ladder_side);
515
516        ladder.add(BookOrder {
517            price: ladder_price,
518            size: Quantity::from(100),
519            side: ladder_side,
520            order_id: 1,
521        });
522
523        let order = BookOrder {
524            price: Price::from("50.00"),
525            size: Quantity::from(500),
526            side: order_side,
527            order_id: 2,
528        };
529
530        let fills = ladder.simulate_fills(&order);
531
532        assert!(fills.is_empty());
533    }
534
535    #[rstest]
536    fn test_simulate_order_fills_sell_when_far_from_market() {
537        let mut ladder = BookLadder::new(OrderSide::Buy);
538
539        ladder.add(BookOrder {
540            price: Price::from("100.00"),
541            size: Quantity::from(100),
542            side: OrderSide::Buy,
543            order_id: 1,
544        });
545
546        let order = BookOrder {
547            price: Price::from("150.00"), // <-- Simulate a MARKET order
548            size: Quantity::from(500),
549            side: OrderSide::Buy,
550            order_id: 2,
551        };
552
553        let fills = ladder.simulate_fills(&order);
554
555        assert!(fills.is_empty());
556    }
557
558    #[rstest]
559    fn test_simulate_order_fills_buy() {
560        let mut ladder = BookLadder::new(OrderSide::Sell);
561
562        ladder.add_bulk(vec![
563            BookOrder {
564                price: Price::from("100.00"),
565                size: Quantity::from(100),
566                side: OrderSide::Sell,
567                order_id: 1,
568            },
569            BookOrder {
570                price: Price::from("101.00"),
571                size: Quantity::from(200),
572                side: OrderSide::Sell,
573                order_id: 2,
574            },
575            BookOrder {
576                price: Price::from("102.00"),
577                size: Quantity::from(400),
578                side: OrderSide::Sell,
579                order_id: 3,
580            },
581        ]);
582
583        let order = BookOrder {
584            price: Price::max(2), // <-- Simulate a MARKET order
585            size: Quantity::from(500),
586            side: OrderSide::Buy,
587            order_id: 4,
588        };
589
590        let fills = ladder.simulate_fills(&order);
591
592        assert_eq!(fills.len(), 3);
593
594        let (price1, size1) = fills[0];
595        assert_eq!(price1, Price::from("100.00"));
596        assert_eq!(size1, Quantity::from(100));
597
598        let (price2, size2) = fills[1];
599        assert_eq!(price2, Price::from("101.00"));
600        assert_eq!(size2, Quantity::from(200));
601
602        let (price3, size3) = fills[2];
603        assert_eq!(price3, Price::from("102.00"));
604        assert_eq!(size3, Quantity::from(200));
605    }
606
607    #[rstest]
608    fn test_simulate_order_fills_sell() {
609        let mut ladder = BookLadder::new(OrderSide::Buy);
610
611        ladder.add_bulk(vec![
612            BookOrder {
613                price: Price::from("102.00"),
614                size: Quantity::from(100),
615                side: OrderSide::Buy,
616                order_id: 1,
617            },
618            BookOrder {
619                price: Price::from("101.00"),
620                size: Quantity::from(200),
621                side: OrderSide::Buy,
622                order_id: 2,
623            },
624            BookOrder {
625                price: Price::from("100.00"),
626                size: Quantity::from(400),
627                side: OrderSide::Buy,
628                order_id: 3,
629            },
630        ]);
631
632        let order = BookOrder {
633            price: Price::min(2), // <-- Simulate a MARKET order
634            size: Quantity::from(500),
635            side: OrderSide::Sell,
636            order_id: 4,
637        };
638
639        let fills = ladder.simulate_fills(&order);
640
641        assert_eq!(fills.len(), 3);
642
643        let (price1, size1) = fills[0];
644        assert_eq!(price1, Price::from("102.00"));
645        assert_eq!(size1, Quantity::from(100));
646
647        let (price2, size2) = fills[1];
648        assert_eq!(price2, Price::from("101.00"));
649        assert_eq!(size2, Quantity::from(200));
650
651        let (price3, size3) = fills[2];
652        assert_eq!(price3, Price::from("100.00"));
653        assert_eq!(size3, Quantity::from(200));
654    }
655
656    #[rstest]
657    fn test_simulate_order_fills_sell_with_size_at_limit_of_precision() {
658        let mut ladder = BookLadder::new(OrderSide::Buy);
659
660        ladder.add_bulk(vec![
661            BookOrder {
662                price: Price::from("102.00"),
663                size: Quantity::from("100.000000000"),
664                side: OrderSide::Buy,
665                order_id: 1,
666            },
667            BookOrder {
668                price: Price::from("101.00"),
669                size: Quantity::from("200.000000000"),
670                side: OrderSide::Buy,
671                order_id: 2,
672            },
673            BookOrder {
674                price: Price::from("100.00"),
675                size: Quantity::from("400.000000000"),
676                side: OrderSide::Buy,
677                order_id: 3,
678            },
679        ]);
680
681        let order = BookOrder {
682            price: Price::min(2),                  // <-- Simulate a MARKET order
683            size: Quantity::from("699.999999999"), // <-- Size slightly less than total size in ladder
684            side: OrderSide::Sell,
685            order_id: 4,
686        };
687
688        let fills = ladder.simulate_fills(&order);
689
690        assert_eq!(fills.len(), 3);
691
692        let (price1, size1) = fills[0];
693        assert_eq!(price1, Price::from("102.00"));
694        assert_eq!(size1, Quantity::from("100.000000000"));
695
696        let (price2, size2) = fills[1];
697        assert_eq!(price2, Price::from("101.00"));
698        assert_eq!(size2, Quantity::from("200.000000000"));
699
700        let (price3, size3) = fills[2];
701        assert_eq!(price3, Price::from("100.00"));
702        assert_eq!(size3, Quantity::from("399.999999999"));
703    }
704
705    #[rstest]
706    fn test_boundary_prices() {
707        let max_price = Price::max(1);
708        let min_price = Price::min(1);
709
710        let mut ladder_buy = BookLadder::new(OrderSide::Buy);
711        let mut ladder_sell = BookLadder::new(OrderSide::Sell);
712
713        let order_buy = BookOrder::new(OrderSide::Buy, min_price, Quantity::from(1), 1);
714        let order_sell = BookOrder::new(OrderSide::Sell, max_price, Quantity::from(1), 1);
715
716        ladder_buy.add(order_buy);
717        ladder_sell.add(order_sell);
718
719        assert_eq!(ladder_buy.top().unwrap().price.value, min_price);
720        assert_eq!(ladder_sell.top().unwrap().price.value, max_price);
721    }
722}